Message ID | 62415ffc97ff2db4fa65cdd6f9db6ddead8105cd.1703010806.git.osandov@osandov.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [fstests] btrfs: test snapshotting a deleted subvolume | expand |
On 20/12/2023 00:04, Omar Sandoval wrote: > 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> looks good. Reviewed-by: Anand Jain <anand.jain@oracle.com> Added to the staging branch git@github.com:asj/fstests.git staging Thx, Anand > --- > Note that the kernel fix was just sent and isn't yet merged. > > Thanks! > > .gitignore | 1 + > src/Makefile | 2 +- > src/t_snapshot_deleted_subvolume.c | 102 +++++++++++++++++++++++++++++ > tests/btrfs/304 | 26 ++++++++ > tests/btrfs/304.out | 2 + > 5 files changed, 132 insertions(+), 1 deletion(-) > create mode 100644 src/t_snapshot_deleted_subvolume.c > create mode 100755 tests/btrfs/304 > create mode 100644 tests/btrfs/304.out > > diff --git a/.gitignore b/.gitignore > index 4c32ac42..b9bf708b 100644 > --- a/.gitignore > +++ b/.gitignore > @@ -165,6 +165,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 > diff --git a/src/Makefile b/src/Makefile > index 8160a0e8..53a32370 100644 > --- a/src/Makefile > +++ b/src/Makefile > @@ -33,7 +33,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 > index 00000000..c3adb1c4 > --- /dev/null > +++ b/src/t_snapshot_deleted_subvolume.c > @@ -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/304 b/tests/btrfs/304 > new file mode 100755 > index 00000000..65f54b95 > --- /dev/null > +++ b/tests/btrfs/304 > @@ -0,0 +1,26 @@ > +#! /bin/bash > +# SPDX-License-Identifier: GPL-2.0 > +# Copyright (c) Meta Platforms, Inc. and affiliates. > +# > +# FS QA Test 304 > +# > +# 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_Aby_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/304.out b/tests/btrfs/304.out > new file mode 100644 > index 00000000..c504111c > --- /dev/null > +++ b/tests/btrfs/304.out > @@ -0,0 +1,2 @@ > +QA output created by 304 > +Silence is golden
diff --git a/.gitignore b/.gitignore index 4c32ac42..b9bf708b 100644 --- a/.gitignore +++ b/.gitignore @@ -165,6 +165,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 diff --git a/src/Makefile b/src/Makefile index 8160a0e8..53a32370 100644 --- a/src/Makefile +++ b/src/Makefile @@ -33,7 +33,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 index 00000000..c3adb1c4 --- /dev/null +++ b/src/t_snapshot_deleted_subvolume.c @@ -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/304 b/tests/btrfs/304 new file mode 100755 index 00000000..65f54b95 --- /dev/null +++ b/tests/btrfs/304 @@ -0,0 +1,26 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# FS QA Test 304 +# +# 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/304.out b/tests/btrfs/304.out new file mode 100644 index 00000000..c504111c --- /dev/null +++ b/tests/btrfs/304.out @@ -0,0 +1,2 @@ +QA output created by 304 +Silence is golden
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> --- Note that the kernel fix was just sent and isn't yet merged. Thanks! .gitignore | 1 + src/Makefile | 2 +- src/t_snapshot_deleted_subvolume.c | 102 +++++++++++++++++++++++++++++ tests/btrfs/304 | 26 ++++++++ tests/btrfs/304.out | 2 + 5 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 src/t_snapshot_deleted_subvolume.c create mode 100755 tests/btrfs/304 create mode 100644 tests/btrfs/304.out