mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-25 18:40:19 -04:00
Rework snapshot interface
This commit is contained in:
parent
16b08201a4
commit
ec9ddb474a
6 changed files with 147 additions and 157 deletions
|
|
@ -811,8 +811,7 @@ struct snapraid_disk* disk_alloc(const char* name, const char* dir, uint64_t dev
|
|||
pathslash(disk->mount_point, sizeof(disk->mount_point));
|
||||
|
||||
/* no snapshot by default */
|
||||
disk->snapshot_root[0] = 0;
|
||||
disk->snapshot_magic = 0;
|
||||
memset(&disk->fss, 0, sizeof(disk->fss));
|
||||
pathcpy(disk->dir, sizeof(disk->dir), disk->mount_point);
|
||||
|
||||
#if HAVE_THREAD
|
||||
|
|
|
|||
|
|
@ -377,13 +377,9 @@ struct snapraid_disk {
|
|||
char dir[PATH_MAX];
|
||||
|
||||
/**
|
||||
* Subvolumes root directory.
|
||||
*
|
||||
* Empty if disabled.
|
||||
* It always terminates with /
|
||||
* Snapshot context
|
||||
*/
|
||||
char snapshot_root[PATH_MAX];
|
||||
uint32_t snapshot_magic; /**< Magic number of the snapshot filesystem */
|
||||
struct fssnapshot_struct fss;
|
||||
|
||||
char smartctl[PATH_MAX]; /**< Custom command for smartctl. Empty means auto. */
|
||||
int smartignore[SMART_IGNORE_MAX]; /**< Smart attributes to ignore for this device. */
|
||||
|
|
|
|||
|
|
@ -2062,36 +2062,30 @@ int fsinfo(const char* path, int* has_persistent_inode, int* has_syncronized_har
|
|||
return 0;
|
||||
}
|
||||
|
||||
int fssnapshot(const char* path, char* root, size_t root_size, uint32_t* magic)
|
||||
int fssnapshot(const char* path, struct fssnapshot_struct* fss)
|
||||
{
|
||||
(void)path;
|
||||
(void)root;
|
||||
(void)root_size;
|
||||
(void)magic;
|
||||
(void)fss;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fssnapshot_create(uint32_t magic, const char* source, const char* parent_dir, const char* name)
|
||||
int fssnapshot_create(const struct fssnapshot_struct* fss, const char* name)
|
||||
{
|
||||
(void)magic;
|
||||
(void)source;
|
||||
(void)parent_dir;
|
||||
(void)fss;
|
||||
(void)name;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fssnapshot_delete(uint32_t magic, const char* parent_dir, const char* name)
|
||||
int fssnapshot_delete(const struct fssnapshot_struct* fss, const char* name)
|
||||
{
|
||||
(void)magic;
|
||||
(void)parent_dir;
|
||||
(void)fss;
|
||||
(void)name;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int fssnapshot_rename(uint32_t magic, const char* parent_dir, const char* old_name, const char* new_name)
|
||||
int fssnapshot_rename(const struct fssnapshot_struct* fss, const char* old_name, const char* new_name)
|
||||
{
|
||||
(void)magic;
|
||||
(void)parent_dir;
|
||||
(void)fss;
|
||||
(void)old_name;
|
||||
(void)new_name;
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -364,38 +364,74 @@ int filephy(const char* path, uint64_t size, uint64_t* physical);
|
|||
int fsinfo(const char* path, int* has_persistent_inode, int* has_syncronized_hardlinks, uint64_t* total_space, uint64_t* free_space, char* fstype, size_t fstype_size, char* fslabel, size_t fslabel_size);
|
||||
|
||||
/**
|
||||
* Get the subvolume directory if the underline filesystem support it
|
||||
* @param path Full path of the mount point to check. It must end with /
|
||||
* @param root Set the full path of the subvolume root that contains the specified path. It will end with /.
|
||||
* @param magic Set the magic number of the filesystem
|
||||
* Snapshots context
|
||||
*/
|
||||
int fssnapshot(const char* path, char* root, size_t root_size, uint32_t* magic);
|
||||
struct fssnapshot_struct {
|
||||
/**
|
||||
* Filesystem magic number
|
||||
* 0 if no snapshot support
|
||||
*/
|
||||
uint32_t magic;
|
||||
|
||||
/**
|
||||
* Root directory of the volume/dataset mountpoint.
|
||||
* It ALWAYS terminates with /
|
||||
* - Btrfs/Bcachefs: subvolume root
|
||||
* - ZFS: dataset mountpoint
|
||||
*/
|
||||
char root_dir[PATH_MAX];
|
||||
|
||||
/**
|
||||
* Directory where snapshots are accessible as subdirectories.
|
||||
* It ALWAYS terminates with /
|
||||
* - Btrfs/Bcachefs: real directory (e.g. <root>/.snapraid/)
|
||||
* - ZFS: virtual directory (e.g. <root>/.zfs/snapshot/)
|
||||
*/
|
||||
char snapshot_dir[PATH_MAX];
|
||||
|
||||
/*
|
||||
* Dataset name (ZFS only, e.g. "pool/data").
|
||||
* Empty string for filesystems where not applicable.
|
||||
*/
|
||||
char dataset[PATH_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a snapshot of a subvolume
|
||||
* @param magic The magic number of the filesystem.
|
||||
* @param source Path to the source subvolume.
|
||||
* @param parent_dir Directory where the snapshot should be created.
|
||||
* @param name Name of snapshot.
|
||||
* @return 0 on success, -1 on failure.
|
||||
* Initialize snapshot context from an arbitrary path.
|
||||
*
|
||||
* @param path Full path inside the filesystem (must end with '/')
|
||||
* @param fss Output snapshot context
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int fssnapshot_create(uint32_t magic, const char* source, const char* parent_dir, const char* name);
|
||||
int fssnapshot(const char* path, struct fssnapshot_struct* fss);
|
||||
|
||||
/**
|
||||
* Deletes a subvolume/snapshot.
|
||||
* @param magic The magic number of the filesystem.
|
||||
* @param parent_dir Directory where the snapshot is.
|
||||
* @param name Name of snapshot.
|
||||
* @return 0 on success, -1 on failure.
|
||||
* Create a snapshot of the filesystem root/dataset.
|
||||
*
|
||||
* @param fss Snapshot context
|
||||
* @param name Snapshot name
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int fssnapshot_delete(uint32_t magic, const char* parent_dir, const char* name);
|
||||
int fssnapshot_create(const struct fssnapshot_struct* fss, const char* name);
|
||||
|
||||
/**
|
||||
* Renames a subvolume.
|
||||
* @param magic The magic number of the filesystem.
|
||||
* @return 0 on success, -1 on failure.
|
||||
* Delete a snapshot.
|
||||
*
|
||||
* @param fss Snapshot context
|
||||
* @param name Snapshot name
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int fssnapshot_rename(uint32_t magic, const char* parent_dir, const char* old_name, const char* new_name);
|
||||
int fssnapshot_delete(const struct fssnapshot_struct* fss, const char* name);
|
||||
|
||||
/**
|
||||
* Rename a snapshot.
|
||||
*
|
||||
* @param fss Snapshot context
|
||||
* @param old_name Existing snapshot name
|
||||
* @param new_name New snapshot name
|
||||
* @return 0 on success, -1 on failure
|
||||
*/
|
||||
int fssnapshot_rename(const struct fssnapshot_struct* fss, const char* old_name, const char* new_name);
|
||||
|
||||
/*
|
||||
* Log file.
|
||||
|
|
|
|||
|
|
@ -5810,7 +5810,6 @@ void state_load_ignore_file(tommy_list* filter_list, const char* path, const cha
|
|||
sclose(f);
|
||||
}
|
||||
|
||||
#define SNAPSHOT_CONTAINER ".snapraid"
|
||||
#define SNAPSHOT_PENDING "pending"
|
||||
#define SNAPSHOT_STABLE "stable"
|
||||
|
||||
|
|
@ -5839,53 +5838,37 @@ int state_snapshot_new(struct snapraid_state* state)
|
|||
|
||||
for (tommy_node* i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
char root[PATH_MAX];
|
||||
char container[PATH_MAX];
|
||||
char vol[PATH_MAX];
|
||||
int ret;
|
||||
|
||||
/* check if it supports snapshot */
|
||||
if (fssnapshot(disk->mount_point, root, sizeof(root), &disk->snapshot_magic) != 0)
|
||||
if (fssnapshot(disk->mount_point, &disk->fss) != 0)
|
||||
continue;
|
||||
|
||||
size_t root_len = strlen(root);
|
||||
|
||||
pathcpy(container, sizeof(container), root);
|
||||
pathcat(container, sizeof(container), SNAPSHOT_CONTAINER);
|
||||
|
||||
/* create the snapshot container directory if not existing */
|
||||
ret = mkdir(container, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||
if (ret != 0 && errno != EEXIST) {
|
||||
log_error(errno, "Error creating '%s'. %s.\n", container, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
size_t root_len = strlen(disk->fss.root_dir);
|
||||
|
||||
/* delete a potential previous pending snapshot */
|
||||
if (fssnapshot_delete(disk->snapshot_magic, container, SNAPSHOT_PENDING) != 0) {
|
||||
log_fatal(errno, "Failed to delete pending snapshot in '%s'. %s.\n", container, strerror(errno));
|
||||
if (fssnapshot_delete(&disk->fss, SNAPSHOT_PENDING) != 0) {
|
||||
log_fatal(errno, "Failed to delete pending snapshot in '%s'. %s.\n", disk->fss.snapshot_dir, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* create a new snapshot */
|
||||
if (fssnapshot_create(disk->snapshot_magic, root, container, SNAPSHOT_PENDING) != 0) {
|
||||
log_fatal(errno, "Failed to create pending snapshot '%s'. %s.\n", container, strerror(errno));
|
||||
if (fssnapshot_create(&disk->fss, SNAPSHOT_PENDING) != 0) {
|
||||
log_fatal(errno, "Failed to create pending snapshot '%s'. %s.\n", disk->fss.snapshot_dir, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
msg_progress("Created disk %s pending snapshot...\n", disk->name);
|
||||
|
||||
/* setup the snapshot in use */
|
||||
pathcpy(vol, sizeof(vol), container);
|
||||
pathcat(vol, sizeof(vol), "/" SNAPSHOT_PENDING "/");
|
||||
char vol[PATH_MAX];
|
||||
pathcpy(vol, sizeof(vol), disk->fss.snapshot_dir);
|
||||
pathcat(vol, sizeof(vol), SNAPSHOT_PENDING "/");
|
||||
pathcat(vol, sizeof(vol), disk->mount_point + root_len);
|
||||
|
||||
if (state_snapshot_dir(vol, disk) != 0) {
|
||||
log_error(errno, "Error stating snapshot dir '%s'. %s.\n", vol, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* store the snapshot root */
|
||||
pathcpy(disk->snapshot_root, sizeof(disk->snapshot_root), root);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -5898,24 +5881,20 @@ int state_snapshot_commit(struct snapraid_state* state)
|
|||
|
||||
for (tommy_node* i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
char container[PATH_MAX];
|
||||
|
||||
/* check if it supports snapshot */
|
||||
if (disk->snapshot_root[0] == 0)
|
||||
if (disk->fss.magic == 0)
|
||||
continue;
|
||||
|
||||
pathcpy(container, sizeof(container), disk->snapshot_root);
|
||||
pathcat(container, sizeof(container), SNAPSHOT_CONTAINER);
|
||||
|
||||
/* delete a potential previous stable snapshot */
|
||||
if (fssnapshot_delete(disk->snapshot_magic, container, SNAPSHOT_STABLE) != 0) {
|
||||
log_fatal(errno, "Failed to delete stable snapshot in '%s'. %s.\n", container, strerror(errno));
|
||||
if (fssnapshot_delete(&disk->fss, SNAPSHOT_STABLE) != 0) {
|
||||
log_fatal(errno, "Failed to delete stable snapshot in '%s'. %s.\n", disk->fss.snapshot_dir, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* rename pending to stable */
|
||||
if (fssnapshot_rename(disk->snapshot_magic, container, SNAPSHOT_PENDING, SNAPSHOT_STABLE) != 0) {
|
||||
log_fatal(errno, "Failed to rename snapshot in '%s'. %s.\n", container, strerror(errno));
|
||||
if (fssnapshot_rename(&disk->fss, SNAPSHOT_PENDING, SNAPSHOT_STABLE) != 0) {
|
||||
log_fatal(errno, "Failed to rename snapshot in '%s'. %s.\n", disk->fss.snapshot_dir, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -5932,27 +5911,22 @@ void state_snapshot_read(struct snapraid_state* state)
|
|||
|
||||
for (tommy_node* i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
char root[PATH_MAX];
|
||||
char container[PATH_MAX];
|
||||
char vol[PATH_MAX];
|
||||
|
||||
/* check if it supports snapshot */
|
||||
if (fssnapshot(disk->mount_point, root, sizeof(root), &disk->snapshot_magic) != 0)
|
||||
if (fssnapshot(disk->mount_point, &disk->fss) != 0)
|
||||
continue;
|
||||
|
||||
size_t root_len = strlen(root);
|
||||
size_t root_len = strlen(disk->fss.root_dir);
|
||||
|
||||
pathcpy(container, sizeof(container), root);
|
||||
pathcat(container, sizeof(container), SNAPSHOT_CONTAINER);
|
||||
|
||||
pathcpy(vol, sizeof(vol), container);
|
||||
pathcat(vol, sizeof(vol), "/" SNAPSHOT_PENDING "/");
|
||||
pathcpy(vol, sizeof(vol), disk->fss.snapshot_dir);
|
||||
pathcat(vol, sizeof(vol), SNAPSHOT_PENDING "/");
|
||||
pathcat(vol, sizeof(vol), disk->mount_point + root_len);
|
||||
if (state_snapshot_dir(vol, disk) == 0) {
|
||||
msg_progress("Using disk %s pending snapshot...\n", disk->name);
|
||||
} else {
|
||||
pathcpy(vol, sizeof(vol), container);
|
||||
pathcat(vol, sizeof(vol), "/" SNAPSHOT_STABLE "/");
|
||||
pathcpy(vol, sizeof(vol), disk->fss.snapshot_dir);
|
||||
pathcat(vol, sizeof(vol), SNAPSHOT_STABLE "/");
|
||||
pathcat(vol, sizeof(vol), disk->mount_point + root_len);
|
||||
if (state_snapshot_dir(vol, disk) == 0) {
|
||||
msg_progress("Using disk %s stable snapshot...\n", disk->name);
|
||||
|
|
@ -5977,15 +5951,13 @@ void state_snapshot_write(struct snapraid_state* state, tommy_list* filterlist_d
|
|||
|
||||
for (tommy_node* i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
char root[PATH_MAX];
|
||||
char container[PATH_MAX];
|
||||
char vol[PATH_MAX];
|
||||
|
||||
/* check if it supports snapshot */
|
||||
if (fssnapshot(disk->mount_point, root, sizeof(root), &disk->snapshot_magic) != 0)
|
||||
if (fssnapshot(disk->mount_point, &disk->fss) != 0)
|
||||
continue;
|
||||
|
||||
size_t root_len = strlen(root);
|
||||
size_t root_len = strlen(disk->fss.root_dir);
|
||||
|
||||
/* if the disk is filtered in, it could be written, then we cannot use the snapshot */
|
||||
if (filter_path(filterlist_disk, 0, disk->name, 0) == 0) {
|
||||
|
|
@ -5993,19 +5965,16 @@ void state_snapshot_write(struct snapraid_state* state, tommy_list* filterlist_d
|
|||
continue;
|
||||
}
|
||||
|
||||
pathcpy(container, sizeof(container), root);
|
||||
pathcat(container, sizeof(container), SNAPSHOT_CONTAINER);
|
||||
|
||||
pathcpy(vol, sizeof(vol), container);
|
||||
pathcat(vol, sizeof(vol), "/" SNAPSHOT_PENDING "/");
|
||||
pathcpy(vol, sizeof(vol), disk->fss.snapshot_dir);
|
||||
pathcat(vol, sizeof(vol), SNAPSHOT_PENDING "/");
|
||||
pathcat(vol, sizeof(vol), disk->mount_point + root_len);
|
||||
if (state_snapshot_dir(vol, disk) == 0) {
|
||||
msg_progress("Using disk %s pending snapshot...\n", disk->name);
|
||||
|
||||
/* if there is a dealloc list */
|
||||
if (!tommy_list_empty(&disk->dealloclist)) {
|
||||
pathcpy(vol, sizeof(vol), container);
|
||||
pathcat(vol, sizeof(vol), "/" SNAPSHOT_STABLE "/");
|
||||
pathcpy(vol, sizeof(vol), disk->fss.snapshot_dir);
|
||||
pathcat(vol, sizeof(vol), SNAPSHOT_STABLE "/");
|
||||
pathcat(vol, sizeof(vol), disk->mount_point + root_len);
|
||||
|
||||
/* if there is a previous snapshot */
|
||||
|
|
@ -6016,8 +5985,8 @@ void state_snapshot_write(struct snapraid_state* state, tommy_list* filterlist_d
|
|||
}
|
||||
}
|
||||
} else {
|
||||
pathcpy(vol, sizeof(vol), container);
|
||||
pathcat(vol, sizeof(vol), "/" SNAPSHOT_STABLE "/");
|
||||
pathcpy(vol, sizeof(vol), disk->fss.snapshot_dir);
|
||||
pathcat(vol, sizeof(vol), SNAPSHOT_STABLE "/");
|
||||
pathcat(vol, sizeof(vol), disk->mount_point + root_len);
|
||||
if (state_snapshot_dir(vol, disk) == 0) {
|
||||
msg_progress("Using disk %s stable snapshot...\n", disk->name);
|
||||
|
|
|
|||
104
cmdline/unix.c
104
cmdline/unix.c
|
|
@ -1561,7 +1561,9 @@ static const char* find_bcachefs(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
int fssnapshot(const char* path, char* root, size_t root_size, uint32_t* magic)
|
||||
#define SNAPSHOT_CONTAINER ".snapraid"
|
||||
|
||||
int fssnapshot(const char* path, struct fssnapshot_struct* fss)
|
||||
{
|
||||
#if HAVE_LINUX_DEVICE
|
||||
struct statfs sfs;
|
||||
|
|
@ -1599,8 +1601,18 @@ int fssnapshot(const char* path, char* root, size_t root_size, uint32_t* magic)
|
|||
|
||||
if (st.st_ino == root_inode) {
|
||||
/* copy the subvol root */
|
||||
pathcpy(root, root_size, current_path);
|
||||
*magic = sfs.f_type;
|
||||
pathcpy(fss->snapshot_dir, sizeof(fss->snapshot_dir), current_path);
|
||||
pathcat(fss->snapshot_dir, sizeof(fss->snapshot_dir), SNAPSHOT_CONTAINER "/");
|
||||
|
||||
/* create the snapshot container directory if not existing */
|
||||
int ret = mkdir(fss->snapshot_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||
if (ret != 0 && errno != EEXIST) {
|
||||
log_error(errno, "Error creating '%s'. %s.\n", fss->snapshot_dir, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
pathcpy(fss->root_dir, sizeof(fss->root_dir), current_path);
|
||||
fss->magic = sfs.f_type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1616,15 +1628,13 @@ int fssnapshot(const char* path, char* root, size_t root_size, uint32_t* magic)
|
|||
}
|
||||
#else
|
||||
(void)path;
|
||||
(void)root;
|
||||
(void)root_size;
|
||||
(void)magic;
|
||||
(void)fss;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_LINUX_DEVICE
|
||||
int fssnapshot_btrfs_create(const char* source, const char* parent_dir, const char* name)
|
||||
int fssnapshot_btrfs_create(const struct fssnapshot_struct* fss, const char* name)
|
||||
{
|
||||
struct btrfs_ioctl_vol_args_v2 args;
|
||||
int fd_source;
|
||||
|
|
@ -1632,14 +1642,14 @@ int fssnapshot_btrfs_create(const char* source, const char* parent_dir, const ch
|
|||
int ret;
|
||||
|
||||
/* open the source subvolume to get a file descriptor */
|
||||
fd_source = open(source, O_RDONLY | O_DIRECTORY);
|
||||
fd_source = open(fss->root_dir, O_RDONLY | O_DIRECTORY);
|
||||
if (fd_source < 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
fd_dest_parent = open(parent_dir, O_RDONLY | O_DIRECTORY);
|
||||
fd_dest_parent = open(fss->snapshot_dir, O_RDONLY | O_DIRECTORY);
|
||||
if (fd_dest_parent < 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
close(fd_source);
|
||||
|
|
@ -1670,7 +1680,7 @@ int fssnapshot_btrfs_create(const char* source, const char* parent_dir, const ch
|
|||
#endif
|
||||
|
||||
#if HAVE_LINUX_DEVICE
|
||||
static int fssnapshot_bcachefs_create(const char* source, const char* parent_dir, const char* name)
|
||||
static int fssnapshot_bcachefs_create(const struct fssnapshot_struct* fss, const char* name)
|
||||
{
|
||||
char dst_path[PATH_MAX];
|
||||
char cmd[PATH_MAX * 3 + 64];
|
||||
|
|
@ -1684,11 +1694,10 @@ static int fssnapshot_bcachefs_create(const char* source, const char* parent_dir
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
pathcpy(dst_path, sizeof(dst_path), parent_dir);
|
||||
pathcatc(dst_path, sizeof(dst_path), '/');
|
||||
pathcpy(dst_path, sizeof(dst_path), fss->snapshot_dir);
|
||||
pathcat(dst_path, sizeof(dst_path), name);
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "%s subvolume snapshot -r %s %s", bcachefs, source, dst_path);
|
||||
snprintf(cmd, sizeof(cmd), "%s subvolume snapshot -r %s %s", bcachefs, fss->root_dir, dst_path);
|
||||
|
||||
ret = system(cmd);
|
||||
if (ret != 0) {
|
||||
|
|
@ -1701,33 +1710,31 @@ static int fssnapshot_bcachefs_create(const char* source, const char* parent_dir
|
|||
}
|
||||
#endif
|
||||
|
||||
int fssnapshot_create(uint32_t magic, const char* source, const char* parent_dir, const char* name)
|
||||
int fssnapshot_create(const struct fssnapshot_struct* fss, const char* name)
|
||||
{
|
||||
#if HAVE_LINUX_DEVICE
|
||||
if (magic == BTRFS_SUPER_MAGIC) {
|
||||
return fssnapshot_btrfs_create(source, parent_dir, name);
|
||||
} else if (magic == BCACHEFS_SUPER_MAGIC) {
|
||||
return fssnapshot_bcachefs_create(source, parent_dir, name);
|
||||
if (fss->magic == BTRFS_SUPER_MAGIC) {
|
||||
return fssnapshot_btrfs_create(fss, name);
|
||||
} else if (fss->magic == BCACHEFS_SUPER_MAGIC) {
|
||||
return fssnapshot_bcachefs_create(fss, name);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
(void)magic;
|
||||
(void)source;
|
||||
(void)parent_dir;
|
||||
(void)fss;
|
||||
(void)name;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_LINUX_DEVICE
|
||||
int fssnapshot_btrfs_delete(const char* parent_dir, const char* name)
|
||||
int fssnapshot_btrfs_delete(const struct fssnapshot_struct* fss, const char* name)
|
||||
{
|
||||
struct btrfs_ioctl_vol_args args;
|
||||
int fd_parent;
|
||||
int ret;
|
||||
|
||||
fd_parent = open(parent_dir, O_RDONLY | O_DIRECTORY);
|
||||
fd_parent = open(fss->snapshot_dir, O_RDONLY | O_DIRECTORY);
|
||||
if (fd_parent < 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
return -1;
|
||||
|
|
@ -1751,7 +1758,7 @@ int fssnapshot_btrfs_delete(const char* parent_dir, const char* name)
|
|||
#endif
|
||||
|
||||
#if HAVE_LINUX_DEVICE
|
||||
static int fssnapshot_bcachefs_delete(const char* parent_dir, const char* name)
|
||||
static int fssnapshot_bcachefs_delete(const struct fssnapshot_struct* fss, const char* name)
|
||||
{
|
||||
char target_path[PATH_MAX];
|
||||
char cmd[PATH_MAX + 64];
|
||||
|
|
@ -1765,8 +1772,7 @@ static int fssnapshot_bcachefs_delete(const char* parent_dir, const char* name)
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
pathcpy(target_path, sizeof(target_path), parent_dir);
|
||||
pathcatc(target_path, sizeof(target_path), '/');
|
||||
pathcpy(target_path, sizeof(target_path), fss->snapshot_dir);
|
||||
pathcat(target_path, sizeof(target_path), name);
|
||||
|
||||
if (access(target_path, F_OK) < 0) {
|
||||
|
|
@ -1790,35 +1796,32 @@ static int fssnapshot_bcachefs_delete(const char* parent_dir, const char* name)
|
|||
}
|
||||
#endif
|
||||
|
||||
int fssnapshot_delete(uint32_t magic, const char* parent_dir, const char* name)
|
||||
int fssnapshot_delete(const struct fssnapshot_struct* fss, const char* name)
|
||||
{
|
||||
#if HAVE_LINUX_DEVICE
|
||||
if (magic == BTRFS_SUPER_MAGIC) {
|
||||
return fssnapshot_btrfs_delete(parent_dir, name);
|
||||
} else if (magic == BCACHEFS_SUPER_MAGIC) {
|
||||
return fssnapshot_bcachefs_delete(parent_dir, name);
|
||||
if (fss->magic == BTRFS_SUPER_MAGIC) {
|
||||
return fssnapshot_btrfs_delete(fss, name);
|
||||
} else if (fss->magic == BCACHEFS_SUPER_MAGIC) {
|
||||
return fssnapshot_bcachefs_delete(fss, name);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
(void)magic;
|
||||
(void)parent_dir;
|
||||
(void)fss;
|
||||
(void)name;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if HAVE_LINUX_DEVICE
|
||||
static int fssnapshot_btrfs_rename(const char* parent_dir, const char* old_name, const char* new_name)
|
||||
static int fssnapshot_btrfs_rename(const struct fssnapshot_struct* fss, const char* old_name, const char* new_name)
|
||||
{
|
||||
char old_path[PATH_MAX];
|
||||
char new_path[PATH_MAX];
|
||||
|
||||
pathcpy(old_path, sizeof(old_path), parent_dir);
|
||||
pathcatc(old_path, sizeof(old_path), '/');
|
||||
pathcpy(old_path, sizeof(old_path), fss->snapshot_dir);
|
||||
pathcat(old_path, sizeof(old_path), old_name);
|
||||
pathcpy(new_path, sizeof(new_path), parent_dir);
|
||||
pathcatc(new_path, sizeof(new_path), '/');
|
||||
pathcpy(new_path, sizeof(new_path), fss->snapshot_dir);
|
||||
pathcat(new_path, sizeof(new_path), new_name);
|
||||
|
||||
if (rename(old_path, new_path) < 0) {
|
||||
|
|
@ -1832,21 +1835,15 @@ static int fssnapshot_btrfs_rename(const char* parent_dir, const char* old_name,
|
|||
#endif
|
||||
|
||||
#if HAVE_LINUX_DEVICE
|
||||
static int fssnapshot_bcachefs_rename(const char* parent_dir, const char* old_name, const char* new_name)
|
||||
static int fssnapshot_bcachefs_rename(const struct fssnapshot_struct* fss, const char* old_name, const char* new_name)
|
||||
{
|
||||
char old_path[PATH_MAX];
|
||||
|
||||
pathcpy(old_path, sizeof(old_path), parent_dir);
|
||||
pathcatc(old_path, sizeof(old_path), '/');
|
||||
pathcat(old_path, sizeof(old_path), old_name);
|
||||
|
||||
if (fssnapshot_bcachefs_create(old_path, parent_dir, new_name) != 0) {
|
||||
if (fssnapshot_bcachefs_create(fss, new_name) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
if (fssnapshot_bcachefs_delete(parent_dir, old_name) != 0) {
|
||||
if (fssnapshot_bcachefs_delete(fss, old_name) != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
|
|
@ -1856,19 +1853,18 @@ static int fssnapshot_bcachefs_rename(const char* parent_dir, const char* old_na
|
|||
}
|
||||
#endif
|
||||
|
||||
int fssnapshot_rename(uint32_t magic, const char* parent_dir, const char* old_name, const char* new_name)
|
||||
int fssnapshot_rename(const struct fssnapshot_struct* fss, const char* old_name, const char* new_name)
|
||||
{
|
||||
#if HAVE_LINUX_DEVICE
|
||||
if (magic == BTRFS_SUPER_MAGIC) {
|
||||
return fssnapshot_btrfs_rename(parent_dir, old_name, new_name);
|
||||
} else if (magic == BCACHEFS_SUPER_MAGIC) {
|
||||
return fssnapshot_bcachefs_rename(parent_dir, old_name, new_name);
|
||||
if (fss->magic == BTRFS_SUPER_MAGIC) {
|
||||
return fssnapshot_btrfs_rename(fss, old_name, new_name);
|
||||
} else if (fss->magic == BCACHEFS_SUPER_MAGIC) {
|
||||
return fssnapshot_bcachefs_rename(fss, old_name, new_name);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
(void)magic;
|
||||
(void)parent_dir;
|
||||
(void)fss;
|
||||
(void)old_name;
|
||||
(void)new_name;
|
||||
return -1;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue