]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
test: Modernize btrfs tests
authorDaan De Meyer <daan@amutable.com>
Tue, 12 May 2026 07:41:01 +0000 (09:41 +0200)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 13 May 2026 11:47:18 +0000 (13:47 +0200)
Convert test-btrfs to use the test framework and
assertions, merge the physical offset test into it
and beef it up to include what TEST-83-BTRFS does and
finally get rid of TEST-83-BTRFS as it is unneeded now.

src/test/meson.build
src/test/test-btrfs-physical-offset.c [deleted file]
src/test/test-btrfs.c
test/integration-tests/TEST-83-BTRFS/meson.build [deleted file]
test/integration-tests/meson.build
test/units/TEST-83-BTRFS.sh [deleted file]

index 966619c95f6d6062332ae4f701184c4dba779511..f13868d4e12dd4fc690095cfb6fb5eeb8dda93f5 100644 (file)
@@ -256,11 +256,6 @@ executables += [
         },
         test_template + {
                 'sources' : files('test-btrfs.c'),
-                'type' : 'manual',
-        },
-        test_template + {
-                'sources' : files('test-btrfs-physical-offset.c'),
-                'type' : 'manual',
         },
         test_template + {
                 'sources' : files('test-chase-manual.c'),
diff --git a/src/test/test-btrfs-physical-offset.c b/src/test/test-btrfs-physical-offset.c
deleted file mode 100644 (file)
index e039a63..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#include <fcntl.h>
-
-#include "btrfs-util.h"
-#include "fd-util.h"
-#include "log.h"
-#include "memory-util.h"
-#include "tests.h"
-
-int main(int argc, char *argv[]) {
-        _cleanup_close_ int fd = -EBADF;
-        uint64_t offset;
-        int r;
-
-        assert(argc == 2);
-        assert(!isempty(argv[1]));
-
-        test_setup_logging(LOG_DEBUG);
-
-        fd = open(argv[1], O_RDONLY|O_CLOEXEC|O_NOCTTY);
-        if (fd < 0) {
-                log_error_errno(errno, "Failed to open '%s': %m", argv[1]);
-                return EXIT_FAILURE;
-        }
-
-        r = btrfs_get_file_physical_offset_fd(fd, &offset);
-        if (r < 0) {
-                log_error_errno(r, "Failed to get physical offset of '%s': %m", argv[1]);
-                return EXIT_FAILURE;
-        }
-
-        printf("%" PRIu64 "\n", offset / page_size());
-        return EXIT_SUCCESS;
-}
index b3fcf8068ec4637f09b8fc54cd3ba350bdc2cd83..66cb10a4c2534356f730b78b9bcf500d5024f9d6 100644 (file)
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 
 #include <fcntl.h>
+#include <linux/magic.h>
+#include <stdlib.h>
 #include <sys/file.h>
 #include <sys/stat.h>
 
+#include "alloc-util.h"
 #include "btrfs-util.h"
+#include "chattr-util.h"
 #include "fd-util.h"
 #include "fileio.h"
 #include "format-util.h"
 #include "fs-util.h"
 #include "log.h"
+#include "memory-util.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "pidref.h"
+#include "process-util.h"
+#include "rm-rf.h"
+#include "stat-util.h"
 #include "string-util.h"
 #include "tests.h"
 #include "time-util.h"
+#include "tmpfile-util.h"
 
-int main(int argc, char *argv[]) {
-        BtrfsQuotaInfo quota;
-        int r, fd;
+static int open_test_subvol(char **ret_path) {
+        const char *vtd;
+        int r;
 
-        test_setup_logging(LOG_DEBUG);
+        r = var_tmp_dir(&vtd);
+        if (r < 0)
+                return r;
 
-        fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
-        if (fd < 0)
-                log_error_errno(errno, "Failed to open root directory: %m");
-        else {
-                BtrfsSubvolInfo info;
-
-                r = btrfs_subvol_get_info_fd(fd, 0, &info);
-                if (r < 0)
-                        log_error_errno(r, "Failed to get subvolume info: %m");
-                else {
-                        log_info("otime: %s", FORMAT_TIMESTAMP(info.otime));
-                        log_info("read-only (search): %s", yes_no(info.read_only));
-                }
-
-                r = btrfs_qgroup_get_quota_fd(fd, 0, &quota);
-                if (r < 0)
-                        log_error_errno(r, "Failed to get quota info: %m");
-                else {
-                        log_info("referenced: %s", strna(FORMAT_BYTES(quota.referenced)));
-                        log_info("exclusive: %s", strna(FORMAT_BYTES(quota.exclusive)));
-                        log_info("referenced_max: %s", strna(FORMAT_BYTES(quota.referenced_max)));
-                        log_info("exclusive_max: %s", strna(FORMAT_BYTES(quota.exclusive_max)));
-                }
-
-                r = btrfs_subvol_get_read_only_fd(fd);
-                if (r < 0)
-                        log_error_errno(r, "Failed to get read only flag: %m");
-                else
-                        log_info("read-only (ioctl): %s", yes_no(r));
-
-                safe_close(fd);
-        }
+        _cleanup_free_ char *base = path_join(vtd, "test-btrfs"), *p = NULL;
+        if (!base)
+                return -ENOMEM;
 
-        r = btrfs_subvol_make(AT_FDCWD, "/xxxtest");
+        r = tempfn_random(base, /* extra= */ NULL, &p);
         if (r < 0)
-                log_error_errno(r, "Failed to make subvolume: %m");
+                return r;
 
-        r = write_string_file("/xxxtest/file", "ljsadhfljasdkfhlkjdsfha", WRITE_STRING_FILE_CREATE);
-        if (r < 0)
-                log_error_errno(r, "Failed to write file: %m");
+        int fd = xopenat_full(AT_FDCWD, p, O_DIRECTORY|O_CREAT|O_CLOEXEC, XO_SUBVOLUME, MODE_INVALID);
+        if (fd < 0)
+                return fd;
 
-        r = btrfs_subvol_snapshot_at(AT_FDCWD, "/xxxtest", AT_FDCWD, "/xxxtest2", 0);
-        if (r < 0)
-                log_error_errno(r, "Failed to make snapshot: %m");
+        if (ret_path)
+                *ret_path = TAKE_PTR(p);
 
-        r = btrfs_subvol_snapshot_at(AT_FDCWD, "/xxxtest", AT_FDCWD, "/xxxtest3", BTRFS_SNAPSHOT_READ_ONLY);
-        if (r < 0)
-                log_error_errno(r, "Failed to make snapshot: %m");
+        return fd;
+}
 
-        r = btrfs_subvol_snapshot_at(AT_FDCWD, "/xxxtest", AT_FDCWD, "/xxxtest4", BTRFS_SNAPSHOT_LOCK_BSD);
-        if (r < 0)
-                log_error_errno(r, "Failed to make snapshot: %m");
-        if (r >= 0)
-                assert_se(xopenat_lock(AT_FDCWD, "/xxxtest4", 0, LOCK_BSD, LOCK_EX|LOCK_NB) == -EAGAIN);
+TEST(info) {
+        _cleanup_(rm_rf_subvolume_and_freep) char *dir = NULL;
+        _cleanup_close_ int dir_fd = ASSERT_OK(open_test_subvol(&dir));
+        BtrfsSubvolInfo info;
+        BtrfsQuotaInfo quota;
+        int r;
 
-        safe_close(r);
+        ASSERT_OK(btrfs_subvol_get_info_fd(dir_fd, 0, &info));
+        log_info("otime: %s", FORMAT_TIMESTAMP(info.otime));
+        log_info("read-only (search): %s", yes_no(info.read_only));
 
-        r = btrfs_subvol_remove("/xxxtest", BTRFS_REMOVE_QUOTA);
+        r = btrfs_qgroup_get_quota_fd(dir_fd, 0, &quota);
         if (r < 0)
-                log_error_errno(r, "Failed to remove subvolume: %m");
+                log_info_errno(r, "Failed to get quota info: %m");
+        else {
+                log_info("referenced: %s", strna(FORMAT_BYTES(quota.referenced)));
+                log_info("exclusive: %s", strna(FORMAT_BYTES(quota.exclusive)));
+                log_info("referenced_max: %s", strna(FORMAT_BYTES(quota.referenced_max)));
+                log_info("exclusive_max: %s", strna(FORMAT_BYTES(quota.exclusive_max)));
+        }
 
-        r = btrfs_subvol_remove("/xxxtest2", BTRFS_REMOVE_QUOTA);
-        if (r < 0)
-                log_error_errno(r, "Failed to remove subvolume: %m");
+        r = ASSERT_OK(btrfs_subvol_get_read_only_fd(dir_fd));
+        log_info("read-only (ioctl): %s", yes_no(r));
+}
 
-        r = btrfs_subvol_remove("/xxxtest3", BTRFS_REMOVE_QUOTA);
-        if (r < 0)
-                log_error_errno(r, "Failed to remove subvolume: %m");
+TEST(subvol) {
+        _cleanup_(rm_rf_subvolume_and_freep) char *dir = NULL;
+        _cleanup_close_ int dir_fd = ASSERT_OK(open_test_subvol(&dir));
 
-        r = btrfs_subvol_remove("/xxxtest4", BTRFS_REMOVE_QUOTA);
-        if (r < 0)
-                log_error_errno(r, "Failed to remove subvolume: %m");
+        ASSERT_OK(btrfs_subvol_make(dir_fd, "test1"));
+        ASSERT_OK(write_string_file_at(dir_fd, "test1/file", "ljsadhfljasdkfhlkjdsfha", WRITE_STRING_FILE_CREATE));
 
-        r = btrfs_subvol_snapshot_at(AT_FDCWD, "/etc", AT_FDCWD, "/etc2",
-                                     BTRFS_SNAPSHOT_READ_ONLY|BTRFS_SNAPSHOT_FALLBACK_COPY);
-        if (r < 0)
-                log_error_errno(r, "Failed to make snapshot: %m");
+        ASSERT_OK(btrfs_subvol_snapshot_at(dir_fd, "test1", dir_fd, "test2", 0));
+        ASSERT_OK(btrfs_subvol_snapshot_at(dir_fd, "test1", dir_fd, "test3", BTRFS_SNAPSHOT_READ_ONLY));
 
-        r = btrfs_subvol_remove("/etc2", BTRFS_REMOVE_QUOTA);
-        if (r < 0)
-                log_error_errno(r, "Failed to remove subvolume: %m");
+        _unused_ _cleanup_close_ int locked_fd = ASSERT_OK(btrfs_subvol_snapshot_at(dir_fd, "test1", dir_fd, "test4", BTRFS_SNAPSHOT_LOCK_BSD));
+        ASSERT_ERROR(xopenat_lock(dir_fd, "test4", 0, LOCK_BSD, LOCK_EX|LOCK_NB), EAGAIN);
 
-        r = btrfs_subvol_make(AT_FDCWD, "/xxxrectest");
-        if (r < 0)
-                log_error_errno(r, "Failed to make subvolume: %m");
+        /* The destroy ioctl needs CAP_SYS_ADMIN; without it, leave cleanup to rm_rf_subvolume_and_freep. */
+        ASSERT_OK_OR(btrfs_subvol_remove_at(dir_fd, "test1", BTRFS_REMOVE_QUOTA), -EPERM);
+        ASSERT_OK_OR(btrfs_subvol_remove_at(dir_fd, "test2", BTRFS_REMOVE_QUOTA), -EPERM);
+        ASSERT_OK_OR(btrfs_subvol_remove_at(dir_fd, "test3", BTRFS_REMOVE_QUOTA), -EPERM);
+        ASSERT_OK_OR(btrfs_subvol_remove_at(dir_fd, "test4", BTRFS_REMOVE_QUOTA), -EPERM);
+}
 
-        r = btrfs_subvol_make(AT_FDCWD, "/xxxrectest/xxxrectest2");
-        if (r < 0)
-                log_error_errno(r, "Failed to make subvolume: %m");
+TEST(fallback_copy) {
+        _cleanup_(rm_rf_subvolume_and_freep) char *dir = NULL;
+        _cleanup_close_ int dir_fd = ASSERT_OK(open_test_subvol(&dir));
 
-        r = btrfs_subvol_make(AT_FDCWD, "/xxxrectest/xxxrectest3");
-        if (r < 0)
-                log_error_errno(r, "Failed to make subvolume: %m");
+        /* Snapshot a regular directory (not a subvolume) — exercises the FALLBACK_COPY path. */
+        ASSERT_OK_ERRNO(mkdirat(dir_fd, "src", 0755));
+        ASSERT_OK(write_string_file_at(dir_fd, "src/file1", "hello", WRITE_STRING_FILE_CREATE));
+        ASSERT_OK(write_string_file_at(dir_fd, "src/file2", "world", WRITE_STRING_FILE_CREATE));
 
-        r = btrfs_subvol_make(AT_FDCWD, "/xxxrectest/xxxrectest3/sub");
-        if (r < 0)
-                log_error_errno(r, "Failed to make subvolume: %m");
+        ASSERT_OK(btrfs_subvol_snapshot_at(dir_fd, "src", dir_fd, "snap",
+                                           BTRFS_SNAPSHOT_READ_ONLY|BTRFS_SNAPSHOT_FALLBACK_COPY));
 
-        if (mkdir("/xxxrectest/dir", 0755) < 0)
-                log_error_errno(errno, "Failed to make directory: %m");
+        ASSERT_OK_OR(btrfs_subvol_remove_at(dir_fd, "snap", BTRFS_REMOVE_QUOTA), -EPERM);
+}
 
-        r = btrfs_subvol_make(AT_FDCWD, "/xxxrectest/dir/xxxrectest4");
-        if (r < 0)
-                log_error_errno(r, "Failed to make subvolume: %m");
+TEST(recursive) {
+        _cleanup_(rm_rf_subvolume_and_freep) char *dir = NULL;
+        _cleanup_close_ int dir_fd = ASSERT_OK(open_test_subvol(&dir));
 
-        if (mkdir("/xxxrectest/dir/xxxrectest4/dir", 0755) < 0)
-                log_error_errno(errno, "Failed to make directory: %m");
+        ASSERT_OK(btrfs_subvol_make(dir_fd, "rec"));
+        ASSERT_OK(btrfs_subvol_make(dir_fd, "rec/sv2"));
+        ASSERT_OK(btrfs_subvol_make(dir_fd, "rec/sv3"));
+        ASSERT_OK(btrfs_subvol_make(dir_fd, "rec/sv3/sub"));
 
-        r = btrfs_subvol_make(AT_FDCWD, "/xxxrectest/dir/xxxrectest4/dir/xxxrectest5");
-        if (r < 0)
-                log_error_errno(r, "Failed to make subvolume: %m");
+        ASSERT_OK_ERRNO(mkdirat(dir_fd, "rec/dir", 0755));
+        ASSERT_OK(btrfs_subvol_make(dir_fd, "rec/dir/sv4"));
+        ASSERT_OK_ERRNO(mkdirat(dir_fd, "rec/dir/sv4/dir", 0755));
+        ASSERT_OK(btrfs_subvol_make(dir_fd, "rec/dir/sv4/dir/sv5"));
 
-        if (mkdir("/xxxrectest/mnt", 0755) < 0)
-                log_error_errno(errno, "Failed to make directory: %m");
+        ASSERT_OK_ERRNO(mkdirat(dir_fd, "rec/mnt", 0755));
 
-        r = btrfs_subvol_snapshot_at(AT_FDCWD, "/xxxrectest", AT_FDCWD, "/xxxrectest2", BTRFS_SNAPSHOT_RECURSIVE);
-        if (r < 0)
-                log_error_errno(r, "Failed to snapshot subvolume: %m");
+        ASSERT_OK(btrfs_subvol_snapshot_at(dir_fd, "rec", dir_fd, "rec-snap", BTRFS_SNAPSHOT_RECURSIVE));
 
-        r = btrfs_subvol_remove("/xxxrectest", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
-        if (r < 0)
-                log_error_errno(r, "Failed to recursively remove subvolume: %m");
+        ASSERT_OK_OR(btrfs_subvol_remove_at(dir_fd, "rec", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE), -EPERM);
+        ASSERT_OK_OR(btrfs_subvol_remove_at(dir_fd, "rec-snap", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE), -EPERM);
+}
 
-        r = btrfs_subvol_remove("/xxxrectest2", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
-        if (r < 0)
-                log_error_errno(r, "Failed to recursively remove subvolume: %m");
+TEST(quota) {
+        _cleanup_(rm_rf_subvolume_and_freep) char *dir = NULL;
+        _cleanup_close_ int dir_fd = ASSERT_OK(open_test_subvol(&dir));
+        BtrfsQuotaInfo quota;
+        int r;
 
-        r = btrfs_subvol_make(AT_FDCWD, "/xxxquotatest");
-        if (r < 0)
-                log_error_errno(r, "Failed to make subvolume: %m");
+        _cleanup_free_ char *qt = ASSERT_NOT_NULL(path_join(dir, "quotatest")),
+                            *qt2 = ASSERT_NOT_NULL(path_join(dir, "quotatest2")),
+                            *beneath = ASSERT_NOT_NULL(path_join(dir, "quotatest/beneath")),
+                            *snap_beneath = ASSERT_NOT_NULL(path_join(dir, "quotatest2/beneath"));
 
-        r = btrfs_subvol_auto_qgroup("/xxxquotatest", 0, true);
-        if (r < 0)
-                log_error_errno(r, "Failed to set up auto qgroup: %m");
+        ASSERT_OK(btrfs_subvol_make(dir_fd, "quotatest"));
+        /* The qgroup/quota ioctls require CAP_SYS_ADMIN; skip the rest of the test if we don't have it
+         * or quotas are not enabled on this filesystem. */
+        r = btrfs_subvol_auto_qgroup(qt, 0, true);
+        if (r == -EPERM)
+                return (void) log_tests_skipped("not running privileged");
+        if (IN_SET(r, -ENOTCONN, -ENOENT))
+                return (void) log_tests_skipped_errno(r, "btrfs quotas not enabled on this filesystem");
+        ASSERT_OK(r);
 
-        r = btrfs_subvol_make(AT_FDCWD, "/xxxquotatest/beneath");
-        if (r < 0)
-                log_error_errno(r, "Failed to make subvolume: %m");
+        ASSERT_OK(btrfs_subvol_make(dir_fd, "quotatest/beneath"));
+        ASSERT_OK(btrfs_subvol_auto_qgroup(beneath, 0, false));
+        ASSERT_OK(btrfs_qgroup_set_limit(beneath, 0, 4ULL * 1024 * 1024 * 1024));
 
-        r = btrfs_subvol_auto_qgroup("/xxxquotatest/beneath", 0, false);
-        if (r < 0)
-                log_error_errno(r, "Failed to set up auto qgroup: %m");
+        ASSERT_OK(btrfs_subvol_set_subtree_quota_limit(qt, 0, 5ULL * 1024 * 1024 * 1024));
 
-        r = btrfs_qgroup_set_limit("/xxxquotatest/beneath", 0, 4ULL * 1024 * 1024 * 1024);
-        if (r < 0)
-                log_error_errno(r, "Failed to set up quota limit: %m");
+        ASSERT_OK(btrfs_subvol_snapshot_at(dir_fd, "quotatest", dir_fd, "quotatest2",
+                                           BTRFS_SNAPSHOT_RECURSIVE|BTRFS_SNAPSHOT_QUOTA));
 
-        r = btrfs_subvol_set_subtree_quota_limit("/xxxquotatest", 0, 5ULL * 1024 * 1024 * 1024);
-        if (r < 0)
-                log_error_errno(r, "Failed to set up quota limit: %m");
+        ASSERT_OK(btrfs_qgroup_get_quota(snap_beneath, 0, &quota));
+        ASSERT_EQ(quota.referenced_max, 4ULL * 1024 * 1024 * 1024);
 
-        r = btrfs_subvol_snapshot_at(AT_FDCWD, "/xxxquotatest", AT_FDCWD, "/xxxquotatest2",
-                                     BTRFS_SNAPSHOT_RECURSIVE|BTRFS_SNAPSHOT_QUOTA);
-        if (r < 0)
-                log_error_errno(r, "Failed to set up snapshot: %m");
+        ASSERT_OK(btrfs_subvol_get_subtree_quota(qt2, 0, &quota));
+        ASSERT_EQ(quota.referenced_max, 5ULL * 1024 * 1024 * 1024);
+
+        ASSERT_OK_OR(btrfs_subvol_remove_at(dir_fd, "quotatest", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE), -EPERM);
+        ASSERT_OK_OR(btrfs_subvol_remove_at(dir_fd, "quotatest2", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE), -EPERM);
+}
 
-        r = btrfs_qgroup_get_quota("/xxxquotatest2/beneath", 0, &quota);
+TEST(physical_offset) {
+        _cleanup_free_ char *btrfs_progs = NULL;
+        int r = find_executable("btrfs", &btrfs_progs);
         if (r < 0)
-                log_error_errno(r, "Failed to query quota: %m");
+                return (void) log_tests_skipped_errno(r, "btrfs(8) not found");
+
+        _cleanup_(rm_rf_subvolume_and_freep) char *dir = NULL;
+        _cleanup_close_ int dir_fd = ASSERT_OK(open_test_subvol(&dir));
+
+        /* Set NOCOW on the subvol dir so the swapfile inherits it on creation. Older btrfs-progs
+         * versions don't reliably set NOCOW from `btrfs filesystem mkswapfile`. */
+        ASSERT_OK(chattr_fd(dir_fd, FS_NOCOW_FL, FS_NOCOW_FL));
+
+        /* btrfs filesystem mkswapfile produces a NOCOW, contiguous file with a swap header — exactly
+         * what btrfs inspect-internal map-swapfile expects, and what btrfs_get_file_physical_offset_fd
+         * works with. */
+        _cleanup_free_ char *path = ASSERT_NOT_NULL(path_join(dir, "swapfile"));
+        r = ASSERT_OK(pidref_safe_fork("(mkswapfile)",
+                        FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_WAIT,
+                        NULL));
+        if (r == 0) {
+                execlp(btrfs_progs, "btrfs", "filesystem", "mkswapfile", "-s", "1m", path, NULL);
+                _exit(EXIT_FAILURE);
+        }
 
-        if (r >= 0)
-                assert_se(quota.referenced_max == 4ULL * 1024 * 1024 * 1024);
+        _cleanup_close_ int fd = ASSERT_OK_ERRNO(openat(dir_fd, "swapfile", O_RDONLY|O_CLOEXEC|O_NOCTTY));
+
+        unsigned attrs;
+        ASSERT_OK(read_attr_fd(fd, &attrs));
+        if (!FLAGS_SET(attrs, FS_NOCOW_FL) || FLAGS_SET(attrs, FS_COMPR_FL))
+                return (void) log_tests_skipped("swapfile is not NOCOW/non-compressed (old btrfs-progs?)");
+
+        /* btrfs_get_file_physical_offset_fd() uses BTRFS_IOC_TREE_SEARCH, which needs CAP_SYS_ADMIN. */
+        uint64_t offset;
+        r = btrfs_get_file_physical_offset_fd(fd, &offset);
+        if (r == -EPERM)
+                return (void) log_tests_skipped("not running privileged");
+        ASSERT_OK(r);
+
+        /* Cross-check against `btrfs inspect-internal map-swapfile -r`, which prints the first
+         * physical address in page units. */
+        _cleanup_close_pair_ int pipe_fds[2] = EBADF_PAIR;
+        ASSERT_OK_ERRNO(pipe2(pipe_fds, O_CLOEXEC));
+
+        _cleanup_(pidref_done) PidRef inspect = PIDREF_NULL;
+        r = pidref_safe_fork_full("(btrfs-inspect)",
+                                  (int[3]) { -EBADF, pipe_fds[1], STDERR_FILENO },
+                                  /* except_fds= */ NULL, /* n_except_fds= */ 0,
+                                  FORK_RESET_SIGNALS|FORK_RLIMIT_NOFILE_SAFE|FORK_LOG|FORK_REARRANGE_STDIO,
+                                  &inspect);
+        ASSERT_OK(r);
+        if (r == 0) {
+                execlp(btrfs_progs, "btrfs", "inspect-internal", "map-swapfile", "-r", path, NULL);
+                _exit(EXIT_FAILURE);
+        }
+        pipe_fds[1] = safe_close(pipe_fds[1]);
 
-        r = btrfs_subvol_get_subtree_quota("/xxxquotatest2", 0, &quota);
-        if (r < 0)
-                log_error_errno(r, "Failed to query quota: %m");
+        _cleanup_fclose_ FILE *f = ASSERT_NOT_NULL(take_fdopen(&pipe_fds[0], "r"));
+        _cleanup_free_ char *out = NULL;
+        ASSERT_OK(read_full_stream(f, &out, /* ret_size= */ NULL));
+        ASSERT_OK_EQ(pidref_wait_for_terminate_and_check("(btrfs-inspect)", &inspect, 0), 0);
 
-        if (r >= 0)
-                assert_se(quota.referenced_max == 5ULL * 1024 * 1024 * 1024);
+        uint64_t expected;
+        ASSERT_OK(safe_atou64(strstrip(out), &expected));
+        ASSERT_EQ(offset / page_size(), expected);
+        log_info("physical offset: page %" PRIu64, expected);
+}
+
+static int intro(void) {
+        const char *vtd;
+        int r;
 
-        r = btrfs_subvol_remove("/xxxquotatest", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
+        r = var_tmp_dir(&vtd);
         if (r < 0)
-                log_error_errno(r, "Failed to remove subvolume: %m");
+                return log_tests_skipped_errno(r, "Failed to resolve /var/tmp");
 
-        r = btrfs_subvol_remove("/xxxquotatest2", BTRFS_REMOVE_QUOTA|BTRFS_REMOVE_RECURSIVE);
+        r = path_is_fs_type(vtd, BTRFS_SUPER_MAGIC);
         if (r < 0)
-                log_error_errno(r, "Failed to remove subvolume: %m");
+                return log_tests_skipped_errno(r, "Failed to determine filesystem type of %s", vtd);
+        if (r == 0)
+                return log_tests_skipped("%s is not on btrfs", vtd);
 
-        return 0;
+        return EXIT_SUCCESS;
 }
+
+DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro);
diff --git a/test/integration-tests/TEST-83-BTRFS/meson.build b/test/integration-tests/TEST-83-BTRFS/meson.build
deleted file mode 100644 (file)
index 77370ce..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-integration_tests += [
-        integration_test_template + {
-                'name' : fs.name(meson.current_source_dir()),
-                'vm' : true,
-        },
-]
index 7888283db81cb95638fe62027fb83ba0a72f96f8..37ce3915984e21c134ef145e4867d423e3f78266 100644 (file)
@@ -96,7 +96,6 @@ foreach dirname : [
         'TEST-80-NOTIFYACCESS',
         'TEST-81-GENERATORS',
         'TEST-82-SOFTREBOOT',
-        'TEST-83-BTRFS',
         'TEST-84-STORAGETM',
         'TEST-85-NETWORK',
         'TEST-86-MULTI-PROFILE-UKI',
diff --git a/test/units/TEST-83-BTRFS.sh b/test/units/TEST-83-BTRFS.sh
deleted file mode 100755 (executable)
index 4f10ae7..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env bash
-# SPDX-License-Identifier: LGPL-2.1-or-later
-set -eux
-set -o pipefail
-
-FSTYPE="$(stat --file-system --format "%T" /)"
-
-if [[ "$FSTYPE" != "btrfs" ]]; then
-    echo "Root filesystem is $FSTYPE instead of btrfs, skipping"
-    exit 77
-fi
-
-TEST_BTRFS_OFFSET=/usr/lib/systemd/tests/unit-tests/manual/test-btrfs-physical-offset
-
-SWAPFILE=/var/tmp/swapfile
-
-btrfs filesystem mkswapfile -s 10m "$SWAPFILE"
-sync -f "$SWAPFILE"
-
-offset_btrfs_progs="$(btrfs inspect-internal map-swapfile -r "$SWAPFILE")"
-echo "btrfs-progs: $offset_btrfs_progs"
-
-offset_btrfs_util="$("$TEST_BTRFS_OFFSET" "$SWAPFILE")"
-echo "btrfs-util: $offset_btrfs_util"
-
-(( offset_btrfs_progs == offset_btrfs_util ))
-
-rm -f "$SWAPFILE"
-
-/usr/lib/systemd/tests/unit-tests/manual/test-btrfs
-
-touch /testok