Browse Source

src/basic/btrfs-util.*: Add and utilize a few BTRFS functions

sleep-config.c : Check for BTRFS to not allow swap file hibernation,
                 as the detection of swap file offsets is not
                 supported on BTRFS.
copy.c : Utilize btrfs_reflink() and btrfs_clone_range() if
         supported.
rm-rf.c : Utilize subvolume removal if possible.

Signed-off-by: Sven Eden <sven.eden@prydeworx.com>
debian
Sven Eden 1 year ago
parent
commit
cd06d586e0
  1. 6
      src/basic/blockdev-util.c
  2. 2039
      src/basic/btrfs-util.c
  3. 145
      src/basic/btrfs-util.h
  4. 4
      src/basic/copy.c
  5. 2
      src/basic/meson.build
  6. 6
      src/basic/rm-rf.c
  7. 8
      src/shared/sleep-config.c
  8. 1
      src/test/meson.build

6
src/basic/blockdev-util.c

@ -5,7 +5,7 @@
//#include "alloc-util.h"
#include "blockdev-util.h"
//#include "btrfs-util.h"
#include "btrfs-util.h"
//#include "dirent-util.h"
#include "fd-util.h"
//#include "fileio.h"
@ -62,9 +62,7 @@ int block_get_whole_disk(dev_t d, dev_t *ret) {
int get_block_device(const char *path, dev_t *ret) {
_cleanup_close_ int fd = -1;
struct stat st;
#if 0 /// elogind does not support speaking to BTRFS directly
int r;
#endif // 0
assert(path);
assert(ret);
@ -84,13 +82,11 @@ int get_block_device(const char *path, dev_t *ret) {
return 1;
}
#if 0 /// elogind does not support speaking to BTRFS directly
r = btrfs_get_block_device_fd(fd, ret);
if (r > 0)
return 1;
if (r != -ENOTTY) /* not btrfs */
return r;
#endif // 0
*ret = 0;
return 0;

2039
src/basic/btrfs-util.c

File diff suppressed because it is too large

145
src/basic/btrfs-util.h

@ -0,0 +1,145 @@
/* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once
#include <stdbool.h>
#include <stdint.h>
#include <sys/types.h>
#include "sd-id128.h"
#include "copy.h"
#include "time-util.h"
typedef struct BtrfsSubvolInfo {
uint64_t subvol_id;
usec_t otime;
sd_id128_t uuid;
sd_id128_t parent_uuid;
bool read_only;
} BtrfsSubvolInfo;
typedef struct BtrfsQuotaInfo {
uint64_t referenced;
uint64_t exclusive;
uint64_t referenced_max;
uint64_t exclusive_max;
} BtrfsQuotaInfo;
typedef enum BtrfsSnapshotFlags {
BTRFS_SNAPSHOT_FALLBACK_COPY = 1 << 0, /* If the source isn't a subvolume, reflink everything */
BTRFS_SNAPSHOT_READ_ONLY = 1 << 1,
BTRFS_SNAPSHOT_RECURSIVE = 1 << 2,
BTRFS_SNAPSHOT_QUOTA = 1 << 3,
BTRFS_SNAPSHOT_FALLBACK_DIRECTORY = 1 << 4, /* If the destination doesn't support subvolumes, reflink/copy instead */
BTRFS_SNAPSHOT_FALLBACK_IMMUTABLE = 1 << 5, /* When we can't create a subvolume, use the FS_IMMUTABLE attribute for indicating read-only */
BTRFS_SNAPSHOT_SIGINT = 1 << 6, /* Check for SIGINT regularly, and return EINTR if seen */
} BtrfsSnapshotFlags;
typedef enum BtrfsRemoveFlags {
BTRFS_REMOVE_RECURSIVE = 1 << 0,
BTRFS_REMOVE_QUOTA = 1 << 1,
} BtrfsRemoveFlags;
int btrfs_is_filesystem(int fd);
int btrfs_is_subvol_fd(int fd);
#if 0 /// UNNEEDED by elogind
int btrfs_is_subvol(const char *path);
#endif // 0
int btrfs_reflink(int infd, int outfd);
int btrfs_clone_range(int infd, uint64_t in_offset, int ofd, uint64_t out_offset, uint64_t sz);
int btrfs_get_block_device_fd(int fd, dev_t *dev);
#if 0 /// UNNEEDED by elogind
int btrfs_get_block_device(const char *path, dev_t *dev);
int btrfs_defrag_fd(int fd);
int btrfs_defrag(const char *p);
int btrfs_quota_enable_fd(int fd, bool b);
int btrfs_quota_enable(const char *path, bool b);
#endif // 0
int btrfs_quota_scan_start(int fd);
int btrfs_quota_scan_wait(int fd);
#if 0 /// UNNEEDED by elogind
int btrfs_quota_scan_ongoing(int fd);
int btrfs_subvol_make(const char *path);
int btrfs_subvol_make_fd(int fd, const char *subvolume);
int btrfs_subvol_make_fallback(const char *path, mode_t);
int btrfs_subvol_snapshot_fd_full(int old_fd, const char *new_path, BtrfsSnapshotFlags flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata);
static inline int btrfs_subvol_snapshot_fd(int old_fd, const char *new_path, BtrfsSnapshotFlags flags) {
return btrfs_subvol_snapshot_fd_full(old_fd, new_path, flags, NULL, NULL, NULL);
}
int btrfs_subvol_snapshot_full(const char *old_path, const char *new_path, BtrfsSnapshotFlags flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata);
static inline int btrfs_subvol_snapshot(const char *old_path, const char *new_path, BtrfsSnapshotFlags flags) {
return btrfs_subvol_snapshot_full(old_path, new_path, flags, NULL, NULL, NULL);
}
#endif // 0
int btrfs_subvol_remove(const char *path, BtrfsRemoveFlags flags);
int btrfs_subvol_remove_fd(int fd, const char *subvolume, BtrfsRemoveFlags flags);
int btrfs_subvol_set_read_only_fd(int fd, bool b);
#if 0 /// UNNEEDED by elogind
int btrfs_subvol_set_read_only(const char *path, bool b);
int btrfs_subvol_get_read_only_fd(int fd);
int btrfs_subvol_get_id(int fd, const char *subvolume, uint64_t *ret);
#endif // 0
int btrfs_subvol_get_id_fd(int fd, uint64_t *ret);
#if 0 /// UNNEEDED by elogind
int btrfs_subvol_get_parent(int fd, uint64_t subvol_id, uint64_t *ret);
int btrfs_subvol_get_info_fd(int fd, uint64_t subvol_id, BtrfsSubvolInfo *info);
int btrfs_subvol_find_subtree_qgroup(int fd, uint64_t subvol_id, uint64_t *ret);
int btrfs_subvol_get_subtree_quota(const char *path, uint64_t subvol_id, BtrfsQuotaInfo *quota);
int btrfs_subvol_get_subtree_quota_fd(int fd, uint64_t subvol_id, BtrfsQuotaInfo *quota);
int btrfs_subvol_set_subtree_quota_limit(const char *path, uint64_t subvol_id, uint64_t referenced_max);
int btrfs_subvol_set_subtree_quota_limit_fd(int fd, uint64_t subvol_id, uint64_t referenced_max);
int btrfs_subvol_auto_qgroup_fd(int fd, uint64_t subvol_id, bool new_qgroup);
int btrfs_subvol_auto_qgroup(const char *path, uint64_t subvol_id, bool create_intermediary_qgroup);
int btrfs_qgroupid_make(uint64_t level, uint64_t id, uint64_t *ret);
#endif // 0
int btrfs_qgroupid_split(uint64_t qgroupid, uint64_t *level, uint64_t *id);
#if 0 /// UNNEEDED by elogind
int btrfs_qgroup_create(int fd, uint64_t qgroupid);
#endif // 0
int btrfs_qgroup_destroy(int fd, uint64_t qgroupid);
int btrfs_qgroup_destroy_recursive(int fd, uint64_t qgroupid);
#if 0 /// UNNEEDED by elogind
int btrfs_qgroup_set_limit_fd(int fd, uint64_t qgroupid, uint64_t referenced_max);
int btrfs_qgroup_set_limit(const char *path, uint64_t qgroupid, uint64_t referenced_max);
int btrfs_qgroup_copy_limits(int fd, uint64_t old_qgroupid, uint64_t new_qgroupid);
int btrfs_qgroup_assign(int fd, uint64_t child, uint64_t parent);
#endif // 0
int btrfs_qgroup_unassign(int fd, uint64_t child, uint64_t parent);
int btrfs_qgroup_find_parents(int fd, uint64_t qgroupid, uint64_t **ret);
#if 0 /// UNNEEDED by elogind
int btrfs_qgroup_get_quota_fd(int fd, uint64_t qgroupid, BtrfsQuotaInfo *quota);
int btrfs_qgroup_get_quota(const char *path, uint64_t qgroupid, BtrfsQuotaInfo *quota);
static inline int btrfs_log_dev_root(int level, int ret, const char *p) {
return log_full_errno(level, ret,
"File system behind %s is reported by btrfs to be backed by pseudo-device /dev/root, which is not a valid userspace accessible device node. "
"Cannot determine correct backing block device.", p);
}
#endif // 0

4
src/basic/copy.c

@ -13,7 +13,7 @@
#include <unistd.h>
#include "alloc-util.h"
//#include "btrfs-util.h"
#include "btrfs-util.h"
//#include "chattr-util.h"
#include "copy.h"
#include "dirent-util.h"
@ -133,7 +133,6 @@ int copy_bytes_full(
if (ret_remains_size)
*ret_remains_size = 0;
#if 0 /// UNNEEDED by elogind
/* Try btrfs reflinks first. This only works on regular, seekable files, hence let's check the file offsets of
* source and destination first. */
if ((copy_flags & COPY_REFLINK)) {
@ -186,7 +185,6 @@ int copy_bytes_full(
}
}
}
#endif // 0
for (;;) {
ssize_t n;

2
src/basic/meson.build

@ -260,6 +260,8 @@ basic_sources = files('''
audit-util.h
blockdev-util.c
blockdev-util.h
btrfs-util.c
btrfs-util.h
build.h
bus-label.c
bus-label.h

6
src/basic/rm-rf.c

@ -7,7 +7,7 @@
#include <unistd.h>
#include "alloc-util.h"
//#include "btrfs-util.h"
#include "btrfs-util.h"
#include "cgroup-util.h"
#include "dirent-util.h"
#include "fd-util.h"
@ -107,7 +107,6 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
if (r > 0)
continue;
#if 0 /// elogind does not support BTRFS this directly
if ((flags & REMOVE_SUBVOLUME) && st.st_ino == 256) {
/* This could be a subvolume, try to remove it */
@ -126,7 +125,6 @@ int rm_rf_children(int fd, RemoveFlags flags, struct stat *root_dev) {
/* It was a subvolume, continue. */
continue;
}
#endif // 0
/* We pass REMOVE_PHYSICAL here, to avoid doing the fstatfs() to check the file
* system type again for each directory */
@ -168,7 +166,6 @@ int rm_rf(const char *path, RemoveFlags flags) {
"Attempted to remove entire root file system (\"%s\"), and we can't allow that.",
path);
#if 0 /// elogind does not support BTRFS this directly
if (FLAGS_SET(flags, REMOVE_SUBVOLUME | REMOVE_ROOT | REMOVE_PHYSICAL)) {
/* Try to remove as subvolume first */
r = btrfs_subvol_remove(path, BTRFS_REMOVE_RECURSIVE|BTRFS_REMOVE_QUOTA);
@ -183,7 +180,6 @@ int rm_rf(const char *path, RemoveFlags flags) {
/* Not btrfs or not a subvolume */
}
#endif // 0
fd = open(path, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
if (fd < 0) {

8
src/shared/sleep-config.c

@ -16,7 +16,7 @@
#include "alloc-util.h"
#include "blockdev-util.h"
//#include "btrfs-util.h"
#include "btrfs-util.h"
#include "conf-parser.h"
#include "def.h"
#include "env-util.h"
@ -311,11 +311,7 @@ static int calculate_swap_file_offset(const SwapEntry *swap, uint64_t *ret_offse
_cleanup_close_ int fd = -1;
_cleanup_free_ struct fiemap *fiemap = NULL;
struct stat sb;
#if 0 /// elogind does not directly support BTRFS
int r, btrfs;
#else // 0
int r;
#endif // 0
assert(swap);
assert(swap->device);
@ -328,7 +324,6 @@ static int calculate_swap_file_offset(const SwapEntry *swap, uint64_t *ret_offse
if (fstat(fd, &sb) < 0)
return log_debug_errno(errno, "Failed to stat %s: %m", swap->device);
#if 0 /// elogind does not directly support BTRFS
btrfs = btrfs_is_filesystem(fd);
if (btrfs < 0)
return log_debug_errno(btrfs, "Error checking %s for Btrfs filesystem: %m", swap->device);
@ -337,7 +332,6 @@ static int calculate_swap_file_offset(const SwapEntry *swap, uint64_t *ret_offse
*ret_offset = UINT64_MAX;
return 0;
}
#endif // 0
r = read_fiemap(fd, &fiemap);
if (r < 0)

1
src/test/meson.build

@ -606,7 +606,6 @@ tests += [
# [],
# '', 'manual'],
#
#
# [['src/test/test-firewall-util.c'],
# [libshared],
# [],

Loading…
Cancel
Save