]> www.infradead.org Git - users/hch/xfstests-dev.git/commitdiff
btrfs: test snapshotting a deleted subvolume
authorOmar Sandoval <osandov@osandov.com>
Tue, 19 Dec 2023 18:34:37 +0000 (10:34 -0800)
committerZorro Lang <zlang@kernel.org>
Sun, 14 Jan 2024 12:39:09 +0000 (20:39 +0800)
This is a regression test for patch "btrfs: don't abort filesystem when
attempting to snapshot deleted subvolume". Without the fix, the
filesystem goes read-only and prints a warning. With the fix, it should
fail gracefully with ENOENT.

Signed-off-by: Omar Sandoval <osandov@osandov.com>
Reviewed-by: Anand Jain <anand.jain@oracle.com>
Signed-off-by: Zorro Lang <zlang@kernel.org>
.gitignore
src/Makefile
src/t_snapshot_deleted_subvolume.c [new file with mode: 0644]
tests/btrfs/309 [new file with mode: 0755]
tests/btrfs/309.out [new file with mode: 0644]

index 7508b6e8b282efec61d2f42f0f22a5834c782b08..5cc3a5e4ae57f5b021a75c33a689cc8ec4ac3de6 100644 (file)
@@ -166,6 +166,7 @@ tags
 /src/t_readdir_2
 /src/t_readdir_3
 /src/t_rename_overwrite
+/src/t_snapshot_deleted_subvolume
 /src/t_stripealign
 /src/t_truncate_cmtime
 /src/t_truncate_self
index d79015cef41eada193a68e180ce2827fbf9ca31e..e7442487bca190a4469b258051709ef747e18d7b 100644 (file)
@@ -34,7 +34,7 @@ LINUX_TARGETS = xfsctl bstat t_mtab getdevicesize preallo_rw_pattern_reader \
        attr_replace_test swapon mkswap t_attr_corruption t_open_tmpfiles \
        fscrypt-crypt-util bulkstat_null_ocount splice-test chprojid_fail \
        detached_mounts_propagation ext4_resize t_readdir_3 splice2pipe \
-       uuid_ioctl
+       uuid_ioctl t_snapshot_deleted_subvolume
 
 EXTRA_EXECS = dmerror fill2attr fill2fs fill2fs_check scaleread.sh \
              btrfs_crc32c_forged_name.py popdir.pl popattr.py \
diff --git a/src/t_snapshot_deleted_subvolume.c b/src/t_snapshot_deleted_subvolume.c
new file mode 100644 (file)
index 0000000..c3adb1c
--- /dev/null
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) Meta Platforms, Inc. and affiliates.
+
+#include "global.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <linux/types.h>
+#ifdef HAVE_STRUCT_BTRFS_IOCTL_VOL_ARGS_V2
+#include <linux/btrfs.h>
+#else
+#ifndef BTRFS_IOCTL_MAGIC
+#define BTRFS_IOCTL_MAGIC 0x94
+#endif
+
+#ifndef BTRFS_IOC_SNAP_DESTROY_V2
+#define BTRFS_IOC_SNAP_DESTROY_V2 \
+       _IOW(BTRFS_IOCTL_MAGIC, 63, struct btrfs_ioctl_vol_args_v2)
+#endif
+
+#ifndef BTRFS_IOC_SNAP_CREATE_V2
+#define BTRFS_IOC_SNAP_CREATE_V2 \
+       _IOW(BTRFS_IOCTL_MAGIC, 23, struct btrfs_ioctl_vol_args_v2)
+#endif
+
+#ifndef BTRFS_IOC_SUBVOL_CREATE_V2
+#define BTRFS_IOC_SUBVOL_CREATE_V2 \
+       _IOW(BTRFS_IOCTL_MAGIC, 24, struct btrfs_ioctl_vol_args_v2)
+#endif
+
+#ifndef BTRFS_SUBVOL_NAME_MAX
+#define BTRFS_SUBVOL_NAME_MAX 4039
+#endif
+
+struct btrfs_ioctl_vol_args_v2 {
+       __s64 fd;
+       __u64 transid;
+       __u64 flags;
+       union {
+               struct {
+                       __u64 size;
+                       struct btrfs_qgroup_inherit *qgroup_inherit;
+               };
+               __u64 unused[4];
+       };
+       union {
+               char name[BTRFS_SUBVOL_NAME_MAX + 1];
+               __u64 devid;
+               __u64 subvolid;
+       };
+};
+#endif
+
+int main(int argc, char **argv)
+{
+       if (argc != 2) {
+               fprintf(stderr, "usage: %s PATH\n", argv[0]);
+               return EXIT_FAILURE;
+       }
+
+       int dirfd = open(argv[1], O_RDONLY | O_DIRECTORY);
+       if (dirfd < 0) {
+               perror(argv[1]);
+               return EXIT_FAILURE;
+       }
+
+       struct btrfs_ioctl_vol_args_v2 subvol_args = {};
+       strcpy(subvol_args.name, "subvol");
+       if (ioctl(dirfd, BTRFS_IOC_SUBVOL_CREATE_V2, &subvol_args) < 0) {
+               perror("BTRFS_IOC_SUBVOL_CREATE_V2");
+               return EXIT_FAILURE;
+       }
+
+       int subvolfd = openat(dirfd, "subvol", O_RDONLY | O_DIRECTORY);
+       if (subvolfd < 0) {
+               perror("openat");
+               return EXIT_FAILURE;
+       }
+
+       if (ioctl(dirfd, BTRFS_IOC_SNAP_DESTROY_V2, &subvol_args) < 0) {
+               perror("BTRFS_IOC_SNAP_DESTROY_V2");
+               return EXIT_FAILURE;
+       }
+
+       struct btrfs_ioctl_vol_args_v2 snap_args = { .fd = subvolfd };
+       strcpy(snap_args.name, "snap");
+       if (ioctl(dirfd, BTRFS_IOC_SNAP_CREATE_V2, &snap_args) < 0) {
+               if (errno == ENOENT)
+                       return EXIT_SUCCESS;
+               perror("BTRFS_IOC_SNAP_CREATE_V2");
+               return EXIT_FAILURE;
+       }
+       fprintf(stderr, "BTRFS_IOC_SNAP_CREATE_V2 should've failed\n");
+       return EXIT_FAILURE;
+}
diff --git a/tests/btrfs/309 b/tests/btrfs/309
new file mode 100755 (executable)
index 0000000..5cbcd22
--- /dev/null
@@ -0,0 +1,27 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) Meta Platforms, Inc. and affiliates.
+#
+# FS QA Test 309
+#
+# Try to snapshot a deleted subvolume.
+#
+. ./common/preamble
+_begin_fstest auto quick snapshot subvol
+
+_supported_fs btrfs
+_require_scratch
+_require_test_program t_snapshot_deleted_subvolume
+_fixed_by_kernel_commit XXXXXXXXXXXX \
+       "btrfs: don't abort filesystem when attempting to snapshot deleted subvolume"
+
+_scratch_mkfs >> $seqres.full 2>&1 || _fail "mkfs failed"
+_scratch_mount
+
+"$here/src/t_snapshot_deleted_subvolume" "$SCRATCH_MNT"
+# Make sure the filesystem didn't go read-only.
+touch "$SCRATCH_MNT/foo"
+
+echo "Silence is golden"
+status=0
+exit
diff --git a/tests/btrfs/309.out b/tests/btrfs/309.out
new file mode 100644 (file)
index 0000000..56330d6
--- /dev/null
@@ -0,0 +1,2 @@
+QA output created by 309
+Silence is golden