From patchwork Wed Mar 1 02:59:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13155494 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7882DC64EC4 for ; Wed, 1 Mar 2023 02:59:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229675AbjCAC7M (ORCPT ); Tue, 28 Feb 2023 21:59:12 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39592 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229600AbjCAC7M (ORCPT ); Tue, 28 Feb 2023 21:59:12 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 391174C14; Tue, 28 Feb 2023 18:59:11 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id C9DD86122C; Wed, 1 Mar 2023 02:59:10 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3052BC433D2; Wed, 1 Mar 2023 02:59:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1677639550; bh=2XUqCDN5obPTVw6gdUTST5T79HLXXgbtO6UGKb5NSBo=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=q6YHsriHGOXuuLsASr8DDLmaQkzQ1Zarih2Bb5J5NMmcKLvgUrEqKQtPUaQQZhYV1 o6eqwPWCv9Zr0ENNjLX/nDUb8F/A3f/D9Xaya7ikB2e9MliYgV9e/V/2jZiIdvP8Qj 14W2LOR19yVCSXbrOWKFnYaV0+/XV31iwY2C3HuAnnfm/9799eUs4TfUpseurfJ9NU Ov0miAz+R5+CzrUNTbmyXNO/rcGH1EBL7HhhPqxSEUm/eRPMOdthwyLKQGZxV8rI2V OPNmzl4dTWKBx26fDVyCaugDGRd1oIUpk4YhTOAB2RmnTsQptOBLAm7Jgf5oeT3p7F ttWag8mvp4mzA== Subject: [PATCH 1/7] xfs/122: fix for swapext log items From: "Darrick J. Wong" To: djwong@kernel.org, zlang@redhat.com Cc: linux-xfs@vger.kernel.org, fstests@vger.kernel.org, guan@eryu.me Date: Tue, 28 Feb 2023 18:59:09 -0800 Message-ID: <167763954976.3796922.18383591838839702382.stgit@magnolia> In-Reply-To: <167763954409.3796922.11086772690906428270.stgit@magnolia> References: <167763954409.3796922.11086772690906428270.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Add entries for the extent swapping log items. Signed-off-by: Darrick J. Wong --- tests/xfs/122.out | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/xfs/122.out b/tests/xfs/122.out index 95e53c5081..21549db7fd 100644 --- a/tests/xfs/122.out +++ b/tests/xfs/122.out @@ -117,6 +117,9 @@ sizeof(struct xfs_rtrmap_root) = 4 sizeof(struct xfs_rud_log_format) = 16 sizeof(struct xfs_rui_log_format) = 16 sizeof(struct xfs_scrub_metadata) = 64 +sizeof(struct xfs_swap_extent) = 64 +sizeof(struct xfs_sxd_log_format) = 16 +sizeof(struct xfs_sxi_log_format) = 80 sizeof(struct xfs_unmount_log_format) = 8 sizeof(xfs_agf_t) = 224 sizeof(xfs_agfl_t) = 36 From patchwork Wed Mar 1 02:59:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13155495 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 37ADBC64EC7 for ; Wed, 1 Mar 2023 02:59:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229691AbjCAC7V (ORCPT ); Tue, 28 Feb 2023 21:59:21 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39686 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229612AbjCAC7U (ORCPT ); Tue, 28 Feb 2023 21:59:20 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6E5EE4C14; Tue, 28 Feb 2023 18:59:18 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 37B9EB80E95; Wed, 1 Mar 2023 02:59:17 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id C7CB5C433D2; Wed, 1 Mar 2023 02:59:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1677639555; bh=z5jAZdyweqsbJxuPAl7Txq4qb0aWFYzUx5yfHvBpjGU=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=hY7PKxbZXx3gfiL9wUemnxyfHqCjqlpjd/YskDyFL2fn8k0+qzRSNqzKIG6BYHX3r BUE3/9PNrvoWEJOgDhaKte7ltuiN6ECzjbd6RwCqKKVZtQH3NykzrZInFBCYYXVJap /q0IP32vTZmYzZHuYUp4UhevjniI/wkgansbqwUrLp8sEl2A/xwqD+eV4NLUUX69Vo 0TAh5XKorFn0McrH2NVXrVAw/nc0WBk2TtA/+SSnmSErCnSaGpo7gDG74nPEmeVkkW lowiSAaNyAfspNIq1JYRRGHyH6LNe+8kDOq/O0SeojYvSRjSQBhYfgxAhI3XIzRoNB VXAXi3VzDmLdA== Subject: [PATCH 2/7] generic: test old xfs extent swapping ioctl From: "Darrick J. Wong" To: djwong@kernel.org, zlang@redhat.com Cc: linux-xfs@vger.kernel.org, fstests@vger.kernel.org, guan@eryu.me Date: Tue, 28 Feb 2023 18:59:15 -0800 Message-ID: <167763955534.3796922.18393943074107557823.stgit@magnolia> In-Reply-To: <167763954409.3796922.11086772690906428270.stgit@magnolia> References: <167763954409.3796922.11086772690906428270.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Add some tests to check the operation of the old xfs swapext ioctl. There aren't any xfs-specific pieces in here, so they're in generic/ Signed-off-by: Darrick J. Wong --- common/rc | 11 +++++++++ doc/group-names.txt | 2 ++ tests/generic/1200 | 55 +++++++++++++++++++++++++++++++++++++++++++++ tests/generic/1200.out | 3 ++ tests/generic/1201 | 53 +++++++++++++++++++++++++++++++++++++++++++ tests/generic/1201.out | 4 +++ tests/generic/1202 | 47 ++++++++++++++++++++++++++++++++++++++ tests/generic/1202.out | 2 ++ tests/xfs/1202 | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/1202.out | 12 ++++++++++ tests/xfs/537 | 2 +- 11 files changed, 249 insertions(+), 1 deletion(-) create mode 100755 tests/generic/1200 create mode 100644 tests/generic/1200.out create mode 100755 tests/generic/1201 create mode 100644 tests/generic/1201.out create mode 100755 tests/generic/1202 create mode 100644 tests/generic/1202.out create mode 100755 tests/xfs/1202 create mode 100644 tests/xfs/1202.out diff --git a/common/rc b/common/rc index 6852af79b4..caf87db47b 100644 --- a/common/rc +++ b/common/rc @@ -2581,6 +2581,17 @@ _require_xfs_io_command() echo $testio | grep -q "Inappropriate ioctl" && \ _notrun "xfs_io $command support is missing" ;; + "swapext") + $XFS_IO_PROG -f -c 'pwrite -S 0x58 0 128k -b 128k' $testfile > /dev/null + $XFS_IO_PROG -f -c 'truncate 128k' $testfile.1 > /dev/null + testio=`$XFS_IO_PROG -c "$command $param $testfile.1" $testfile 2>&1` + echo $testio | grep -q "bad argument count" && \ + _notrun "xfs_io $command $param support is missing" + echo $testio | grep -q "Inappropriate ioctl" && \ + _notrun "xfs_io $command $param ioctl support is missing" + rm -f $testfile.1 + param_checked="$param" + ;; "utimes" ) testio=`$XFS_IO_PROG -f -c "utimes 0 0 0 0" $testfile 2>&1` ;; diff --git a/doc/group-names.txt b/doc/group-names.txt index ace59e05d9..a0ae6965a8 100644 --- a/doc/group-names.txt +++ b/doc/group-names.txt @@ -52,6 +52,7 @@ enospc ENOSPC error reporting exportfs file handles fiemap fiemap ioctl filestreams XFS filestreams allocator +fiexchange FIEXCHANGE_RANGE ioctl freeze filesystem freeze tests fsck general fsck tests fsmap FS_IOC_GETFSMAP ioctl @@ -123,6 +124,7 @@ splice splice system call stress fsstress filesystem exerciser subvol btrfs subvolumes swap swap files +swapext XFS_IOC_SWAPEXT ioctl symlink symbolic links tape dump and restore with a tape thin thin provisioning diff --git a/tests/generic/1200 b/tests/generic/1200 new file mode 100755 index 0000000000..58b93e2b6e --- /dev/null +++ b/tests/generic/1200 @@ -0,0 +1,55 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1200 +# +# Can we use swapext to make the quota accounting incorrect? + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext quota + +# Import common functions. +. ./common/filter +. ./common/quota + +# real QA test starts here +_require_xfs_io_command swapext '-v vfs' +_require_user +_require_nobody +_require_quota +_require_xfs_quota +_require_scratch + +# Format filesystem and set up quota limits +_scratch_mkfs > $seqres.full +_qmount_option "usrquota,grpquota" +_qmount >> $seqres.full + +# Set up initial files +$XFS_IO_PROG -f -c 'pwrite -S 0x58 0 256k -b 1m' $SCRATCH_MNT/a >> $seqres.full +chown $qa_user $SCRATCH_MNT/a +$XFS_IO_PROG -f -c 'pwrite -S 0x59 0 64k -b 64k' -c 'truncate 256k' $SCRATCH_MNT/b >> $seqres.full +chown nobody $SCRATCH_MNT/b + +echo before swapext >> $seqres.full +$XFS_QUOTA_PROG -x -c 'report -a' $SCRATCH_MNT >> $seqres.full +stat $SCRATCH_MNT/* >> $seqres.full + +# Now try to swap the extents of the two files. The command is allowed to +# fail with -EINVAL (since that's what the first kernel fix does) or succeed +# (because subsequent rewrites can handle quota). Whatever the outcome, the +# quota usage check at the end should never show a discrepancy. +$XFS_IO_PROG -c "swapext $SCRATCH_MNT/b" $SCRATCH_MNT/a &> $tmp.swap +cat $tmp.swap >> $seqres.full +grep -v 'Invalid argument' $tmp.swap + +echo after swapext >> $seqres.full +$XFS_QUOTA_PROG -x -c 'report -a' $SCRATCH_MNT >> $seqres.full +stat $SCRATCH_MNT/* >> $seqres.full + +_check_quota_usage + +# success, all done +status=0 +exit diff --git a/tests/generic/1200.out b/tests/generic/1200.out new file mode 100644 index 0000000000..b1a6357719 --- /dev/null +++ b/tests/generic/1200.out @@ -0,0 +1,3 @@ +QA output created by 1200 +Comparing user usage +Comparing group usage diff --git a/tests/generic/1201 b/tests/generic/1201 new file mode 100755 index 0000000000..91e3773eaa --- /dev/null +++ b/tests/generic/1201 @@ -0,0 +1,53 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1201 +# +# Can we use swapext to exceed the quota enforcement? + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext quota + +# Import common functions. +. ./common/filter +. ./common/quota + +# real QA test starts here +_require_xfs_io_command swapext '-v vfs' +_require_user +_require_nobody +_require_quota +_require_xfs_quota +_require_scratch + +# Format filesystem and set up quota limits +_scratch_mkfs > $seqres.full +_qmount_option "usrquota,grpquota" +_qmount >> $seqres.full + +# Set up initial files +$XFS_IO_PROG -f -c 'pwrite -S 0x58 0 256k -b 1m' $SCRATCH_MNT/a >> $seqres.full +chown $qa_user $SCRATCH_MNT/a +$XFS_IO_PROG -f -c 'pwrite -S 0x59 0 64k -b 64k' -c 'truncate 256k' $SCRATCH_MNT/b >> $seqres.full +chown nobody $SCRATCH_MNT/b + +# Set up a quota limit +$XFS_QUOTA_PROG -x -c "limit -u bhard=70k nobody" $SCRATCH_MNT + +echo before swapext >> $seqres.full +$XFS_QUOTA_PROG -x -c 'report -a' $SCRATCH_MNT >> $seqres.full +stat $SCRATCH_MNT/* >> $seqres.full + +# Now try to swapext +$XFS_IO_PROG -c "swapext $SCRATCH_MNT/b" $SCRATCH_MNT/a + +echo after swapext >> $seqres.full +$XFS_QUOTA_PROG -x -c 'report -a' $SCRATCH_MNT >> $seqres.full +stat $SCRATCH_MNT/* >> $seqres.full + +_check_quota_usage + +# success, all done +status=0 +exit diff --git a/tests/generic/1201.out b/tests/generic/1201.out new file mode 100644 index 0000000000..9001a59958 --- /dev/null +++ b/tests/generic/1201.out @@ -0,0 +1,4 @@ +QA output created by 1201 +swapext: Disk quota exceeded +Comparing user usage +Comparing group usage diff --git a/tests/generic/1202 b/tests/generic/1202 new file mode 100755 index 0000000000..2afa546f1f --- /dev/null +++ b/tests/generic/1202 @@ -0,0 +1,47 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1202 +# +# Make sure that swapext won't touch a swap file. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + test -e "$dir/a" && swapoff $dir/a + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter + +# real QA test starts here +_require_xfs_io_command swapext '-v vfs' +_require_test + +dir=$TEST_DIR/test-$seq +mkdir -p $dir + +# Set up a fragmented swapfile and a dummy donor file. +$XFS_IO_PROG -f -c 'pwrite -S 0x58 0 32m -b 1m' -c fsync $dir/a >> $seqres.full +$here/src/punch-alternating $dir/a +$XFS_IO_PROG -f -c 'pwrite -S 0x58 0 32m -b 1m' -c fsync $dir/a >> $seqres.full +$MKSWAP_PROG $dir/a >> $seqres.full + +$XFS_IO_PROG -f -c 'pwrite -S 0x59 0 32m -b 1m' $dir/b >> $seqres.full + +swapon $dir/a || _notrun 'failed to swapon' + +# Now try to swapext. The old code would return EINVAL for swapfiles +# even though everything else in the VFS returns ETXTBSY. +$XFS_IO_PROG -c "swapext $dir/b" $dir/a 2>&1 | \ + sed -e 's/swapext: Invalid argument/swapext: Text file busy/g' + +# success, all done +status=0 +exit diff --git a/tests/generic/1202.out b/tests/generic/1202.out new file mode 100644 index 0000000000..029d65e4d0 --- /dev/null +++ b/tests/generic/1202.out @@ -0,0 +1,2 @@ +QA output created by 1202 +swapext: Text file busy diff --git a/tests/xfs/1202 b/tests/xfs/1202 new file mode 100755 index 0000000000..73e56641af --- /dev/null +++ b/tests/xfs/1202 @@ -0,0 +1,59 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1202 +# +# Simple tests of the old xfs swapext ioctl + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter + +# real QA test starts here +_supported_fs xfs +_require_xfs_io_command swapext '-v vfs' +_require_test + +# We can't do any reasonable swapping if the files we're going to create are +# realtime files, the rt extent size is greater than 1 block, and we can't use +# atomic extent swapping to make sure that partially written extents are fully +# swapped. +file_blksz=$(_get_file_block_size $TEST_DIR) +fs_blksz=$(_get_block_size $TEST_DIR) +if (( $file_blksz != $fs_blksz )); then + _xfs_has_feature $TEST_DIR reflink || \ + _notrun "test requires atomic extent swapping for rextsize=$((file_blksz / fs_blksz))" +fi + +dir=$TEST_DIR/test-$seq +mkdir -p $dir + +$XFS_IO_PROG -f -c 'pwrite -S 0x58 0 256k -b 1m' $dir/a >> $seqres.full +$XFS_IO_PROG -f -c 'pwrite -S 0x59 0 256k -b 1m' $dir/b >> $seqres.full +$XFS_IO_PROG -f -c 'pwrite -S 0x60 0 256k -b 1m' $dir/c >> $seqres.full +$XFS_IO_PROG -f -c 'pwrite -S 0x61 0 128k -b 1m' $dir/d >> $seqres.full +md5sum $dir/a $dir/b $dir/c $dir/d | _filter_test_dir + +# Swap two files that are the same length +echo swap +$XFS_IO_PROG -c "swapext $dir/b" $dir/a +md5sum $dir/a $dir/b | _filter_test_dir + +# Try to swap two files that are not the same length +echo fail swap +$XFS_IO_PROG -c "swapext $dir/c" $dir/d +md5sum $dir/c $dir/d | _filter_test_dir + +# success, all done +status=0 +exit diff --git a/tests/xfs/1202.out b/tests/xfs/1202.out new file mode 100644 index 0000000000..23127eb7b7 --- /dev/null +++ b/tests/xfs/1202.out @@ -0,0 +1,12 @@ +QA output created by 1202 +af5c6e2d6c297f3139a4e99df396c072 TEST_DIR/test-1202/a +fba5c83875b2ab054e06a0284346ebdf TEST_DIR/test-1202/b +40c08c6f2aca19bb0d2cf1dbd8bc1b1c TEST_DIR/test-1202/c +81615449a98aaaad8dc179b3bec87f38 TEST_DIR/test-1202/d +swap +fba5c83875b2ab054e06a0284346ebdf TEST_DIR/test-1202/a +af5c6e2d6c297f3139a4e99df396c072 TEST_DIR/test-1202/b +fail swap +swapext: Bad address +40c08c6f2aca19bb0d2cf1dbd8bc1b1c TEST_DIR/test-1202/c +81615449a98aaaad8dc179b3bec87f38 TEST_DIR/test-1202/d diff --git a/tests/xfs/537 b/tests/xfs/537 index 7e11488799..6364db9b5d 100755 --- a/tests/xfs/537 +++ b/tests/xfs/537 @@ -7,7 +7,7 @@ # Verify that XFS does not cause inode fork's extent count to overflow when # swapping forks between files . ./common/preamble -_begin_fstest auto quick collapse +_begin_fstest auto quick collapse swapext # Import common functions. . ./common/filter From patchwork Wed Mar 1 02:59:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13155529 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BDC4FC7EE32 for ; Wed, 1 Mar 2023 02:59:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229744AbjCAC73 (ORCPT ); Tue, 28 Feb 2023 21:59:29 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39810 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229589AbjCAC71 (ORCPT ); Tue, 28 Feb 2023 21:59:27 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9FFC17EFD; Tue, 28 Feb 2023 18:59:22 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 1D64961219; Wed, 1 Mar 2023 02:59:22 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6B990C4339C; Wed, 1 Mar 2023 02:59:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1677639561; bh=f/oYwARQ/K4zF/03OIoBR1dl/AiphECwU/AEUWerJWU=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=f7bK8JHJ2Vra/Cyx2MFQt3zD+VaTmLLAR7Y24D4RXDzlfrIxI4XpmwHMAnxE4rcuW qFYUaXYqcOBfMcOYlHf6LlxY/JQVKPwmV9MvMNc/uw7tNpLg/mJpl0r1PwftnAGIjP iKyRz2XCqAUcjWHYBca/fi6O/dp0m5NE4ZaptIq6UfNYnnNk3VWHjxtD/sxhk+3yJf 6VUdaWDjxEmY7kAqu8/x+6CHSNM9UXkbARdUUVouWyk1BkBwH0V/LsYyw03hgHM6KG f2V+OHNiy2Irh7FZOW0j5S6sEZz7jwkzY5HZxUht9Sy3lg9Fu6uG1cQ0N/sIFIZzyi j8w4gV2NjbvRQ== Subject: [PATCH 3/7] generic: test new vfs swapext ioctl From: "Darrick J. Wong" To: djwong@kernel.org, zlang@redhat.com Cc: linux-xfs@vger.kernel.org, fstests@vger.kernel.org, guan@eryu.me Date: Tue, 28 Feb 2023 18:59:21 -0800 Message-ID: <167763956100.3796922.13813179976151740616.stgit@magnolia> In-Reply-To: <167763954409.3796922.11086772690906428270.stgit@magnolia> References: <167763954409.3796922.11086772690906428270.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Test the new vfs swapext ioctl. Signed-off-by: Darrick J. Wong --- common/rc | 13 +++++ common/reflink | 33 +++++++++++++ tests/generic/1203 | 58 ++++++++++++++++++++++ tests/generic/1203.out | 2 + tests/generic/1204 | 100 ++++++++++++++++++++++++++++++++++++++ tests/generic/1204.out | 86 +++++++++++++++++++++++++++++++++ tests/generic/1205 | 116 ++++++++++++++++++++++++++++++++++++++++++++ tests/generic/1205.out | 90 ++++++++++++++++++++++++++++++++++ tests/generic/1206 | 76 +++++++++++++++++++++++++++++ tests/generic/1206.out | 32 ++++++++++++ tests/generic/1207 | 122 ++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/1207.out | 48 ++++++++++++++++++ tests/generic/1209 | 101 ++++++++++++++++++++++++++++++++++++++ tests/generic/1209.out | 33 +++++++++++++ tests/generic/1210 | 48 ++++++++++++++++++ tests/generic/1210.out | 6 ++ tests/generic/1211 | 105 ++++++++++++++++++++++++++++++++++++++++ tests/generic/1211.out | 40 +++++++++++++++ tests/generic/1212 | 58 ++++++++++++++++++++++ tests/generic/1212.out | 2 + tests/generic/1213 | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/1213.out | 48 ++++++++++++++++++ tests/generic/1214 | 63 ++++++++++++++++++++++++ tests/generic/1214.out | 2 + tests/generic/1215 | 70 +++++++++++++++++++++++++++ tests/generic/1215.out | 2 + tests/xfs/1208 | 62 ++++++++++++++++++++++++ tests/xfs/1208.out | 10 ++++ 28 files changed, 1552 insertions(+) create mode 100755 tests/generic/1203 create mode 100644 tests/generic/1203.out create mode 100755 tests/generic/1204 create mode 100644 tests/generic/1204.out create mode 100755 tests/generic/1205 create mode 100644 tests/generic/1205.out create mode 100755 tests/generic/1206 create mode 100644 tests/generic/1206.out create mode 100755 tests/generic/1207 create mode 100644 tests/generic/1207.out create mode 100755 tests/generic/1209 create mode 100644 tests/generic/1209.out create mode 100755 tests/generic/1210 create mode 100644 tests/generic/1210.out create mode 100755 tests/generic/1211 create mode 100644 tests/generic/1211.out create mode 100755 tests/generic/1212 create mode 100644 tests/generic/1212.out create mode 100755 tests/generic/1213 create mode 100644 tests/generic/1213.out create mode 100755 tests/generic/1214 create mode 100644 tests/generic/1214.out create mode 100755 tests/generic/1215 create mode 100644 tests/generic/1215.out create mode 100755 tests/xfs/1208 create mode 100644 tests/xfs/1208.out diff --git a/common/rc b/common/rc index caf87db47b..6b16c6aab0 100644 --- a/common/rc +++ b/common/rc @@ -2581,6 +2581,17 @@ _require_xfs_io_command() echo $testio | grep -q "Inappropriate ioctl" && \ _notrun "xfs_io $command support is missing" ;; + "startupdate"|"commitupdate"|"cancelupdate") + $XFS_IO_PROG -f -c 'pwrite -S 0x58 0 128k -b 128k' $testfile > /dev/null + testio=$($XFS_IO_PROG -c "startupdate $param" \ + -c 'pwrite -S 0x59 0 192k' \ + -c 'commitupdate' $testfile 2>&1) + echo $testio | grep -q "Inappropriate ioctl" && \ + _notrun "xfs_io $command $param support is missing" + echo $testio | grep -q "Operation not supported" && \ + _notrun "xfs_io $command $param kernel support is missing" + param_checked="$param" + ;; "swapext") $XFS_IO_PROG -f -c 'pwrite -S 0x58 0 128k -b 128k' $testfile > /dev/null $XFS_IO_PROG -f -c 'truncate 128k' $testfile.1 > /dev/null @@ -2589,6 +2600,8 @@ _require_xfs_io_command() _notrun "xfs_io $command $param support is missing" echo $testio | grep -q "Inappropriate ioctl" && \ _notrun "xfs_io $command $param ioctl support is missing" + echo $testio | grep -q "Operation not supported" && \ + _notrun "xfs_io $command $param kernel support is missing" rm -f $testfile.1 param_checked="$param" ;; diff --git a/common/reflink b/common/reflink index 76e9cb7d32..22adc4449b 100644 --- a/common/reflink +++ b/common/reflink @@ -325,6 +325,39 @@ _weave_reflink_regular() { done } +# Create a file of interleaved holes, unwritten blocks, and regular blocks. +_weave_file_rainbow() { + blksz=$1 + nr=$2 + dfile=$3 + + $XFS_IO_PROG -f -c "truncate $((blksz * nr))" $dfile + _pwrite_byte 0x00 0 $((blksz * nr)) $dfile.chk + # 0 blocks are unwritten + seq 1 5 $((nr - 1)) | while read i; do + $XFS_IO_PROG -f -c "falloc $((blksz * i)) $blksz" $dfile + _pwrite_byte 0x00 $((blksz * i)) $blksz $dfile.chk + done + # 1 blocks are holes + seq 2 5 $((nr - 1)) | while read i; do + _pwrite_byte 0x00 $((blksz * i)) $blksz $dfile.chk + done + # 2 blocks are regular + seq 3 5 $((nr - 1)) | while read i; do + _pwrite_byte 0x71 $((blksz * i)) $blksz $dfile + _pwrite_byte 0x71 $((blksz * i)) $blksz $dfile.chk + done + # 3 blocks are holes + seq 2 5 $((nr - 1)) | while read i; do + _pwrite_byte 0x00 $((blksz * i)) $blksz $dfile.chk + done + # 4 blocks are delalloc + seq 4 5 $((nr - 1)) | while read i; do + _pwrite_byte 0x62 $((blksz * i)) $blksz $dfile + _pwrite_byte 0x62 $((blksz * i)) $blksz $dfile.chk + done +} + # Create a file of interleaved holes, unwritten blocks, regular blocks, and # reflinked blocks _weave_reflink_rainbow() { diff --git a/tests/generic/1203 b/tests/generic/1203 new file mode 100755 index 0000000000..890b0b4c86 --- /dev/null +++ b/tests/generic/1203 @@ -0,0 +1,58 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1202 +# +# Make sure that swapext modifies ctime and not mtime of the file. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter + +# real QA test starts here +_require_test_program punch-alternating +_require_xfs_io_command swapext '-v vfs' +_require_test + +dir=$TEST_DIR/test-$seq +mkdir -p $dir + +# Set up initial files +$XFS_IO_PROG -f -c 'pwrite -S 0x58 0 256k -b 1m' $dir/a >> $seqres.full +$here/src/punch-alternating $dir/a +$XFS_IO_PROG -f -c 'pwrite -S 0x59 0 256k -b 1m' $dir/b >> $seqres.full + +# Snapshot the 'a' file before we swap +echo before >> $seqres.full +md5sum $dir/a $dir/b >> $seqres.full +old_mtime="$(echo $(stat -c '%y' $dir/a $dir/b))" +old_ctime="$(echo $(stat -c '%z' $dir/a $dir/b))" +stat -c '%y %Y %z %Z' $dir/a $dir/b >> $seqres.full + +# Now try to swapext +$XFS_IO_PROG -c "swapext $dir/b" $dir/a + +# Snapshot the 'a' file after we swap +echo after >> $seqres.full +md5sum $dir/a $dir/b >> $seqres.full +new_mtime="$(echo $(stat -c '%y' $dir/a $dir/b))" +new_ctime="$(echo $(stat -c '%z' $dir/a $dir/b))" +stat -c '%y %Y %z %Z' $dir/a $dir/b >> $seqres.full + +test "$new_mtime" = "$old_mtime" && echo "mtime: $new_mtime == $old_mtime" +test "$new_ctime" = "$old_ctime" && echo "ctime: $new_ctime == $old_ctime" + +# success, all done +echo Silence is golden. +status=0 +exit diff --git a/tests/generic/1203.out b/tests/generic/1203.out new file mode 100644 index 0000000000..904b25beb4 --- /dev/null +++ b/tests/generic/1203.out @@ -0,0 +1,2 @@ +QA output created by 1203 +Silence is golden. diff --git a/tests/generic/1204 b/tests/generic/1204 new file mode 100755 index 0000000000..9c577466e7 --- /dev/null +++ b/tests/generic/1204 @@ -0,0 +1,100 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1204 +# +# Test swapext between ranges of two different files. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter +. ./common/reflink + +# real QA test starts here +_require_xfs_io_command swapext '-v vfs -s 64k -l 64k' +_require_xfs_io_command "falloc" +_require_test + +filesnap() { + echo "$1" + if [ "$2" != "$3" ]; then + md5sum $2 $3 | _filter_test_dir + else + md5sum $2 | _filter_test_dir + fi +} + +test_swapext_once() { + filesnap "$1: before swapext" $dir/$3 $dir/$4 + $XFS_IO_PROG -c "swapext -v vfs $2 $dir/$3" $dir/$4 + filesnap "$1: after swapext" $dir/$3 $dir/$4 + _test_cycle_mount + filesnap "$1: after cycling mount" $dir/$3 $dir/$4 + echo +} + +test_swapext_two() { + # swapext the same range of two files + test_swapext_once "$*: samerange" \ + "-s $((blksz * 3)) -d $((blksz * 3)) -l $((blksz * 5))" b a + + # swapext different ranges of two files + test_swapext_once "$*: diffrange" \ + "-s $((blksz * 37)) -d $((blksz * 47)) -l $((blksz * 7))" b a + + # swapext overlapping ranges of two files + test_swapext_once "$*: overlap" \ + "-s $((blksz * 17)) -d $((blksz * 23)) -l $((blksz * 7))" b a +} + +dir=$TEST_DIR/test-$seq +mkdir -p $dir +blksz=65536 +nrblks=57 +_require_congruent_file_oplen $TEST_DIR $blksz + +# Set up some simple files for a first test. +rm -rf $dir/a $dir/b +_pwrite_byte 0x58 0 $((blksz * nrblks)) $dir/a >> $seqres.full +_pwrite_byte 0x59 0 $((blksz * nrblks)) $dir/b >> $seqres.full +test_swapext_two "simple" + +# Make some files that don't end an aligned offset. +rm -rf $dir/a $dir/b +_pwrite_byte 0x58 0 $(( (blksz * nrblks) + 37)) $dir/a >> $seqres.full +_pwrite_byte 0x59 0 $(( (blksz * nrblks) + 37)) $dir/b >> $seqres.full +test_swapext_once "unalignedeof" "" a b + +# Set up some crazy rainbow files +rm -rf $dir/a $dir/b +_weave_file_rainbow $blksz $nrblks $dir/a >> $seqres.full +_weave_file_rainbow $blksz $nrblks $dir/b >> $seqres.full +test_swapext_two "rainbow" + +# Now set up a simple file for testing within the same file +rm -rf $dir/c +$XFS_IO_PROG -f -c "pwrite -S 0x58 0 $((blksz * nrblks))" \ + -c "pwrite -S 0x59 $((blksz * nrblks)) $((blksz * nrblks))" \ + $dir/c >> $seqres.full + +# swapext the same offset into the 'X' and 'Y' regions of the file +test_swapext_once "single: sameXandY" \ + "-s $((blksz * 3)) -d $((blksz * (nrblks + 3))) -l $((blksz * 5))" c c + +# swapext the same offset into the 'X' and 'Y' regions of the file +test_swapext_once "single: overlap" \ + "-s $((blksz * 13)) -d $((blksz * 17)) -l $((blksz * 5))" c c + +# success, all done +status=0 +exit diff --git a/tests/generic/1204.out b/tests/generic/1204.out new file mode 100644 index 0000000000..cdf9f7315d --- /dev/null +++ b/tests/generic/1204.out @@ -0,0 +1,86 @@ +QA output created by 1204 +simple: samerange: before swapext +db85d578204631f2b4eb1e73974253c2 TEST_DIR/test-1204/b +d0425612f15c6071022cf7127620f63d TEST_DIR/test-1204/a +simple: samerange: after swapext +20beef1c9ed7de02e4229c69bd43bd8f TEST_DIR/test-1204/b +e7697fa99d08f7eb76fa3fb963fe916a TEST_DIR/test-1204/a +simple: samerange: after cycling mount +20beef1c9ed7de02e4229c69bd43bd8f TEST_DIR/test-1204/b +e7697fa99d08f7eb76fa3fb963fe916a TEST_DIR/test-1204/a + +simple: diffrange: before swapext +20beef1c9ed7de02e4229c69bd43bd8f TEST_DIR/test-1204/b +e7697fa99d08f7eb76fa3fb963fe916a TEST_DIR/test-1204/a +simple: diffrange: after swapext +cd32ce54c295fcdf571ce7f8220fac56 TEST_DIR/test-1204/b +d9771c5bb6d9db00b9abe65a4410e1a6 TEST_DIR/test-1204/a +simple: diffrange: after cycling mount +cd32ce54c295fcdf571ce7f8220fac56 TEST_DIR/test-1204/b +d9771c5bb6d9db00b9abe65a4410e1a6 TEST_DIR/test-1204/a + +simple: overlap: before swapext +cd32ce54c295fcdf571ce7f8220fac56 TEST_DIR/test-1204/b +d9771c5bb6d9db00b9abe65a4410e1a6 TEST_DIR/test-1204/a +simple: overlap: after swapext +e0fff655f6a08fc2f03ee01e4767060c TEST_DIR/test-1204/b +ec7d764c85e583e305028c9cba5b25b6 TEST_DIR/test-1204/a +simple: overlap: after cycling mount +e0fff655f6a08fc2f03ee01e4767060c TEST_DIR/test-1204/b +ec7d764c85e583e305028c9cba5b25b6 TEST_DIR/test-1204/a + +unalignedeof: before swapext +9f8c731a4f1946ffdda8c33e82417f2d TEST_DIR/test-1204/a +7a5d2ba7508226751c835292e28cd227 TEST_DIR/test-1204/b +unalignedeof: after swapext +7a5d2ba7508226751c835292e28cd227 TEST_DIR/test-1204/a +9f8c731a4f1946ffdda8c33e82417f2d TEST_DIR/test-1204/b +unalignedeof: after cycling mount +7a5d2ba7508226751c835292e28cd227 TEST_DIR/test-1204/a +9f8c731a4f1946ffdda8c33e82417f2d TEST_DIR/test-1204/b + +rainbow: samerange: before swapext +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1204/b +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1204/a +rainbow: samerange: after swapext +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1204/b +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1204/a +rainbow: samerange: after cycling mount +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1204/b +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1204/a + +rainbow: diffrange: before swapext +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1204/b +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1204/a +rainbow: diffrange: after swapext +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1204/b +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1204/a +rainbow: diffrange: after cycling mount +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1204/b +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1204/a + +rainbow: overlap: before swapext +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1204/b +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1204/a +rainbow: overlap: after swapext +6753bc585e3c71d53bfaae11d2ffee99 TEST_DIR/test-1204/b +39597abd4d9d0c9ceac22b77eb00c373 TEST_DIR/test-1204/a +rainbow: overlap: after cycling mount +6753bc585e3c71d53bfaae11d2ffee99 TEST_DIR/test-1204/b +39597abd4d9d0c9ceac22b77eb00c373 TEST_DIR/test-1204/a + +single: sameXandY: before swapext +39e17753fa9e923a3b5928e13775e358 TEST_DIR/test-1204/c +single: sameXandY: after swapext +8262c617070703fb0e2a28d8f05e3112 TEST_DIR/test-1204/c +single: sameXandY: after cycling mount +8262c617070703fb0e2a28d8f05e3112 TEST_DIR/test-1204/c + +single: overlap: before swapext +8262c617070703fb0e2a28d8f05e3112 TEST_DIR/test-1204/c +swapext: Invalid argument +single: overlap: after swapext +8262c617070703fb0e2a28d8f05e3112 TEST_DIR/test-1204/c +single: overlap: after cycling mount +8262c617070703fb0e2a28d8f05e3112 TEST_DIR/test-1204/c + diff --git a/tests/generic/1205 b/tests/generic/1205 new file mode 100755 index 0000000000..375e66ad86 --- /dev/null +++ b/tests/generic/1205 @@ -0,0 +1,116 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1205 +# +# Test swapext between ranges of two different files, when one of the files +# is shared. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter +. ./common/reflink + +# real QA test starts here +_require_xfs_io_command swapext '-v vfs' +_require_xfs_io_command "falloc" +_require_test_reflink + +filesnap() { + echo "$1" + if [ "$2" != "$3" ]; then + md5sum $2 $3 | _filter_test_dir + else + md5sum $2 | _filter_test_dir + fi +} + +test_swapext_once() { + filesnap "$1: before swapext" $dir/$3 $dir/$4 + $XFS_IO_PROG -c "swapext -v vfs $2 $dir/$3" $dir/$4 + filesnap "$1: after swapext" $dir/$3 $dir/$4 + _test_cycle_mount + filesnap "$1: after cycling mount" $dir/$3 $dir/$4 + echo +} + +test_swapext_two() { + # swapext the same range of two files + test_swapext_once "$*: samerange" \ + "-s $((blksz * 3)) -d $((blksz * 3)) -l $((blksz * 5))" b a + + # swapext different ranges of two files + test_swapext_once "$*: diffrange" \ + "-s $((blksz * 37)) -d $((blksz * 47)) -l $((blksz * 7))" b a + + # swapext overlapping ranges of two files + test_swapext_once "$*: overlap" \ + "-s $((blksz * 17)) -d $((blksz * 23)) -l $((blksz * 7))" b a + + # Now let's overwrite a entirely to make sure COW works + echo "overwrite A and B entirely" + md5sum $dir/sharea | _filter_test_dir + $XFS_IO_PROG -c "pwrite -S 0x60 0 $((blksz * nrblks))" $dir/a >> $seqres.full + $XFS_IO_PROG -c "pwrite -S 0x60 0 $((blksz * nrblks))" $dir/b >> $seqres.full + md5sum $dir/sharea | _filter_test_dir + _test_cycle_mount + md5sum $dir/sharea | _filter_test_dir + echo +} + +dir=$TEST_DIR/test-$seq +mkdir -p $dir +blksz=65536 +_require_congruent_file_oplen $TEST_DIR $blksz +nrblks=57 + +# Set up some simple files for a first test. +rm -f $dir/a $dir/b $dir/sharea +_pwrite_byte 0x58 0 $((blksz * nrblks)) $dir/a >> $seqres.full +_pwrite_byte 0x59 0 $((blksz * nrblks)) $dir/b >> $seqres.full +_cp_reflink $dir/a $dir/sharea +test_swapext_two "simple" + +# Set up some crazy rainbow files +rm -f $dir/a $dir/b $dir/sharea +_weave_file_rainbow $blksz $nrblks $dir/a >> $seqres.full +_weave_file_rainbow $blksz $nrblks $dir/b >> $seqres.full +_cp_reflink $dir/a $dir/sharea +test_swapext_two "rainbow" + +# Now set up a simple file for testing within the same file +rm -f $dir/c $dir/sharec +$XFS_IO_PROG -f -c "pwrite -S 0x58 0 $((blksz * nrblks))" \ + -c "pwrite -S 0x59 $((blksz * nrblks)) $((blksz * nrblks))" \ + $dir/c >> $seqres.full +_cp_reflink $dir/c $dir/sharec + +# swapext the same offset into the 'X' and 'Y' regions of the file +test_swapext_once "single: sameXandY" \ + "-s $((blksz * 3)) -d $((blksz * (nrblks + 3))) -l $((blksz * 5))" c c + +# swapext the same offset into the 'X' and 'Y' regions of the file +test_swapext_once "single: overlap" \ + "-s $((blksz * 13)) -d $((blksz * 17)) -l $((blksz * 5))" c c + +# Now let's overwrite a entirely to make sure COW works +echo "overwrite C entirely" +md5sum $dir/sharec | _filter_test_dir +$XFS_IO_PROG -c "pwrite -S 0x60 0 $((blksz * nrblks))" $dir/c >> $seqres.full +md5sum $dir/sharec | _filter_test_dir +_test_cycle_mount +md5sum $dir/sharec | _filter_test_dir + +# success, all done +status=0 +exit diff --git a/tests/generic/1205.out b/tests/generic/1205.out new file mode 100644 index 0000000000..9a95742e78 --- /dev/null +++ b/tests/generic/1205.out @@ -0,0 +1,90 @@ +QA output created by 1205 +simple: samerange: before swapext +db85d578204631f2b4eb1e73974253c2 TEST_DIR/test-1205/b +d0425612f15c6071022cf7127620f63d TEST_DIR/test-1205/a +simple: samerange: after swapext +20beef1c9ed7de02e4229c69bd43bd8f TEST_DIR/test-1205/b +e7697fa99d08f7eb76fa3fb963fe916a TEST_DIR/test-1205/a +simple: samerange: after cycling mount +20beef1c9ed7de02e4229c69bd43bd8f TEST_DIR/test-1205/b +e7697fa99d08f7eb76fa3fb963fe916a TEST_DIR/test-1205/a + +simple: diffrange: before swapext +20beef1c9ed7de02e4229c69bd43bd8f TEST_DIR/test-1205/b +e7697fa99d08f7eb76fa3fb963fe916a TEST_DIR/test-1205/a +simple: diffrange: after swapext +cd32ce54c295fcdf571ce7f8220fac56 TEST_DIR/test-1205/b +d9771c5bb6d9db00b9abe65a4410e1a6 TEST_DIR/test-1205/a +simple: diffrange: after cycling mount +cd32ce54c295fcdf571ce7f8220fac56 TEST_DIR/test-1205/b +d9771c5bb6d9db00b9abe65a4410e1a6 TEST_DIR/test-1205/a + +simple: overlap: before swapext +cd32ce54c295fcdf571ce7f8220fac56 TEST_DIR/test-1205/b +d9771c5bb6d9db00b9abe65a4410e1a6 TEST_DIR/test-1205/a +simple: overlap: after swapext +e0fff655f6a08fc2f03ee01e4767060c TEST_DIR/test-1205/b +ec7d764c85e583e305028c9cba5b25b6 TEST_DIR/test-1205/a +simple: overlap: after cycling mount +e0fff655f6a08fc2f03ee01e4767060c TEST_DIR/test-1205/b +ec7d764c85e583e305028c9cba5b25b6 TEST_DIR/test-1205/a + +overwrite A and B entirely +d0425612f15c6071022cf7127620f63d TEST_DIR/test-1205/sharea +d0425612f15c6071022cf7127620f63d TEST_DIR/test-1205/sharea +d0425612f15c6071022cf7127620f63d TEST_DIR/test-1205/sharea + +rainbow: samerange: before swapext +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/b +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/a +rainbow: samerange: after swapext +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/b +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/a +rainbow: samerange: after cycling mount +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/b +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/a + +rainbow: diffrange: before swapext +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/b +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/a +rainbow: diffrange: after swapext +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/b +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/a +rainbow: diffrange: after cycling mount +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/b +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/a + +rainbow: overlap: before swapext +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/b +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/a +rainbow: overlap: after swapext +6753bc585e3c71d53bfaae11d2ffee99 TEST_DIR/test-1205/b +39597abd4d9d0c9ceac22b77eb00c373 TEST_DIR/test-1205/a +rainbow: overlap: after cycling mount +6753bc585e3c71d53bfaae11d2ffee99 TEST_DIR/test-1205/b +39597abd4d9d0c9ceac22b77eb00c373 TEST_DIR/test-1205/a + +overwrite A and B entirely +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/sharea +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/sharea +48b41ee1970eb71064b77181f42634cf TEST_DIR/test-1205/sharea + +single: sameXandY: before swapext +39e17753fa9e923a3b5928e13775e358 TEST_DIR/test-1205/c +single: sameXandY: after swapext +8262c617070703fb0e2a28d8f05e3112 TEST_DIR/test-1205/c +single: sameXandY: after cycling mount +8262c617070703fb0e2a28d8f05e3112 TEST_DIR/test-1205/c + +single: overlap: before swapext +8262c617070703fb0e2a28d8f05e3112 TEST_DIR/test-1205/c +swapext: Invalid argument +single: overlap: after swapext +8262c617070703fb0e2a28d8f05e3112 TEST_DIR/test-1205/c +single: overlap: after cycling mount +8262c617070703fb0e2a28d8f05e3112 TEST_DIR/test-1205/c + +overwrite C entirely +39e17753fa9e923a3b5928e13775e358 TEST_DIR/test-1205/sharec +39e17753fa9e923a3b5928e13775e358 TEST_DIR/test-1205/sharec +39e17753fa9e923a3b5928e13775e358 TEST_DIR/test-1205/sharec diff --git a/tests/generic/1206 b/tests/generic/1206 new file mode 100755 index 0000000000..a4d9dd083e --- /dev/null +++ b/tests/generic/1206 @@ -0,0 +1,76 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1206 +# +# Test swapext between two files of unlike size. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter +. ./common/reflink + +# real QA test starts here +_require_xfs_io_command swapext '-v vfs -s 64k -l 64k' +_require_test + +filesnap() { + echo "$1" + if [ "$2" != "$3" ]; then + md5sum $2 $3 | _filter_test_dir + else + md5sum $2 | _filter_test_dir + fi +} + +test_swapext_once() { + local tag=$1 + local a_len=$2 + local b_len=$3 + local a_off=$4 + local b_off=$5 + local len=$6 + + # len is either a block count or -e to swap to EOF + if [ "$len" != "-e" ]; then + len="-l $((blksz * len))" + fi + + rm -f $dir/a $dir/b + _pwrite_byte 0x58 0 $((blksz * a_len)) $dir/a >> $seqres.full + _pwrite_byte 0x59 0 $((blksz * b_len)) $dir/b >> $seqres.full + filesnap "$tag: before swapext" $dir/a $dir/b + + cmd="swapext -v vfs -s $((blksz * a_off)) -d $((blksz * b_off)) $len $dir/a" + echo "$cmd" >> $seqres.full + $XFS_IO_PROG -c "$cmd" $dir/b + filesnap "$tag: after swapext" $dir/a $dir/b + + _test_cycle_mount + filesnap "$tag: after cycling mount" $dir/a $dir/b + echo +} + +dir=$TEST_DIR/test-$seq +mkdir -p $dir +blksz=65536 + +test_swapext_once "last 5 blocks" 27 37 22 32 5 + +test_swapext_once "whole file to eof" 27 37 0 0 -e + +test_swapext_once "blocks 30-40" 27 37 30 30 10 + +# success, all done +status=0 +exit diff --git a/tests/generic/1206.out b/tests/generic/1206.out new file mode 100644 index 0000000000..82f4185684 --- /dev/null +++ b/tests/generic/1206.out @@ -0,0 +1,32 @@ +QA output created by 1206 +last 5 blocks: before swapext +207ea56e0ccbf50d38fd3a2d842aa170 TEST_DIR/test-1206/a +eb58941d31f5be1e4e22df8c536dd490 TEST_DIR/test-1206/b +last 5 blocks: after swapext +3f34470fe9feb8513d5f3a8538f2c5f3 TEST_DIR/test-1206/a +c3daca7dd9218371cd0dc64f11e4b0bf TEST_DIR/test-1206/b +last 5 blocks: after cycling mount +3f34470fe9feb8513d5f3a8538f2c5f3 TEST_DIR/test-1206/a +c3daca7dd9218371cd0dc64f11e4b0bf TEST_DIR/test-1206/b + +whole file to eof: before swapext +207ea56e0ccbf50d38fd3a2d842aa170 TEST_DIR/test-1206/a +eb58941d31f5be1e4e22df8c536dd490 TEST_DIR/test-1206/b +whole file to eof: after swapext +eb58941d31f5be1e4e22df8c536dd490 TEST_DIR/test-1206/a +207ea56e0ccbf50d38fd3a2d842aa170 TEST_DIR/test-1206/b +whole file to eof: after cycling mount +eb58941d31f5be1e4e22df8c536dd490 TEST_DIR/test-1206/a +207ea56e0ccbf50d38fd3a2d842aa170 TEST_DIR/test-1206/b + +blocks 30-40: before swapext +207ea56e0ccbf50d38fd3a2d842aa170 TEST_DIR/test-1206/a +eb58941d31f5be1e4e22df8c536dd490 TEST_DIR/test-1206/b +swapext: Invalid argument +blocks 30-40: after swapext +207ea56e0ccbf50d38fd3a2d842aa170 TEST_DIR/test-1206/a +eb58941d31f5be1e4e22df8c536dd490 TEST_DIR/test-1206/b +blocks 30-40: after cycling mount +207ea56e0ccbf50d38fd3a2d842aa170 TEST_DIR/test-1206/a +eb58941d31f5be1e4e22df8c536dd490 TEST_DIR/test-1206/b + diff --git a/tests/generic/1207 b/tests/generic/1207 new file mode 100755 index 0000000000..3a69a1ec57 --- /dev/null +++ b/tests/generic/1207 @@ -0,0 +1,122 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1207 +# +# Test atomic file updates when (a) the length is the same; (b) the length +# is different; and (c) someone modifies the original file and we need to +# cancel the update. The file contents are cloned into the staging file, +# and some of the contents are updated. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter +. ./common/reflink + +# real QA test starts here +_require_xfs_io_command swapext '-v vfs' +_require_xfs_io_command startupdate +_require_test_reflink +_require_test + +filesnap() { + echo "$1" + md5sum $2 | _filter_test_dir +} + +mkfile() { + rm -f $dir/a + _pwrite_byte 0x58 0 $((blksz * nrblks)) $dir/a >> $seqres.full + sync +} + +dir=$TEST_DIR/test-$seq +mkdir -p $dir +blksz=65536 +nrblks=64 + +# Use the atomic file update staging prototype in xfs_io to update a file. +mkfile +filesnap "before commit" $dir/a + +$XFS_IO_PROG \ + -c 'startupdate' \ + -c 'pwrite -S 0x60 44k 55k -b 1m' \ + -c 'commitupdate -q' \ + "$dir/a" 2>&1 | _filter_xfs_io | _filter_test_dir + +filesnap "after commit" $dir/a +echo + +# Use the atomic file updates to replace a file with a shorter file. +mkfile +filesnap "before shorten commit" $dir/a + +$XFS_IO_PROG \ + -c 'startupdate' \ + -c 'truncate 55k' \ + -c 'pwrite -S 0x60 0 55k' \ + -c 'commitupdate -q' \ + "$dir/a" 2>&1 | _filter_xfs_io | _filter_test_dir + +filesnap "after shorten commit" $dir/a +echo + +# Use the atomic file updates to replace a file with a longer file. +mkfile +filesnap "before lengthen commit" $dir/a + +$XFS_IO_PROG \ + -c 'startupdate' \ + -c "pwrite -S 0x60 0 $(( (blksz * nrblks) + 37373 ))" \ + -c 'commitupdate -q' \ + "$dir/a" 2>&1 | _filter_xfs_io | _filter_test_dir + +filesnap "after lengthen commit" $dir/a +echo + +# Use the atomic file update staging prototype in xfs_io to cancel updating a +# file. +mkfile +filesnap "before cancel" $dir/a + +$XFS_IO_PROG \ + -c 'startupdate' \ + -c 'pwrite -S 0x60 44k 55k -b 1m' \ + -c 'cancelupdate' \ + "$dir/a" 2>&1 | _filter_xfs_io | _filter_test_dir + +filesnap "after cancel" $dir/a +echo + +# Now try the update but with the A file open separately so that we clobber +# mtime and fail the update. +mkfile +filesnap "before fail commit" $dir/a + +$XFS_IO_PROG \ + -c "open $dir/a" \ + -c 'startupdate' \ + -c 'pwrite -S 0x58 44k 55k -b 1m' \ + -c 'file 0' \ + -c 'close' \ + -c 'pwrite -S 0x61 22k 11k -b 1m' \ + -c 'commitupdate -q' \ + "$dir/a" 2>&1 | _filter_xfs_io | _filter_test_dir + +filesnap "after fail commit" $dir/a +echo + +# success, all done +status=0 +exit diff --git a/tests/generic/1207.out b/tests/generic/1207.out new file mode 100644 index 0000000000..ee33564067 --- /dev/null +++ b/tests/generic/1207.out @@ -0,0 +1,48 @@ +QA output created by 1207 +before commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1207/a +wrote 56320/56320 bytes at offset 45056 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Committed updates to 'TEST_DIR/test-1207/a'. +after commit +bedbd22b58a680219a1225353f6195fa TEST_DIR/test-1207/a + +before shorten commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1207/a +wrote 56320/56320 bytes at offset 0 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Committed updates to 'TEST_DIR/test-1207/a'. +after shorten commit +52353039d89c5f2b76b9003464e5276a TEST_DIR/test-1207/a + +before lengthen commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1207/a +wrote 4231677/4231677 bytes at offset 0 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Committed updates to 'TEST_DIR/test-1207/a'. +after lengthen commit +1839e7c6bf616160dc51b12179db2642 TEST_DIR/test-1207/a + +before cancel +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1207/a +wrote 56320/56320 bytes at offset 45056 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Cancelled updates to 'TEST_DIR/test-1207/a'. +after cancel +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1207/a + +before fail commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1207/a +committing update: Device or resource busy +wrote 56320/56320 bytes at offset 45056 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 56320/56320 bytes at offset 45056 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +[000] TEST_DIR/test-1207/a (xfs,non-sync,non-direct,read-write) + 001 TEST_DIR/test-1207/a (fileupdate) (xfs,non-sync,non-direct,read-write) +[000] TEST_DIR/test-1207/a (fileupdate) (xfs,non-sync,non-direct,read-write) +wrote 11264/11264 bytes at offset 22528 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +after fail commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1207/a + diff --git a/tests/generic/1209 b/tests/generic/1209 new file mode 100755 index 0000000000..6b287654ca --- /dev/null +++ b/tests/generic/1209 @@ -0,0 +1,101 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1209 +# +# Try invalid parameters to see if they fail. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter +. ./common/reflink + +# real QA test starts here +_require_xfs_io_command swapext '-v vfs' +_require_xfs_io_command startupdate +_require_test +_require_scratch +_require_chattr i + +dir=$TEST_DIR/test-$seq +mkdir -p $dir +blksz=65536 +nrblks=64 + +_scratch_mkfs >> $seqres.full +_scratch_mount + +_pwrite_byte 0x58 0 $((blksz * nrblks)) $dir/a >> $seqres.full +_pwrite_byte 0x58 0 $((blksz * nrblks)) $dir/b >> $seqres.full + +echo Immutable files +$XFS_IO_PROG -c 'chattr +i' -c "swapext $dir/b" $dir/a +$CHATTR_PROG -i $dir/a + +echo Readonly files +$XFS_IO_PROG -r -c "swapext $dir/b" $dir/a + +echo Directories +$XFS_IO_PROG -c "swapext $dir/b" $dir + +echo Unaligned ranges +$XFS_IO_PROG -c "swapext -s 37 -d 61 -l 17 $dir/b" $dir/a + +echo file1 range entirely beyond EOF +$XFS_IO_PROG -c "swapext -s $(( blksz * (nrblks + 500) )) -d 0 -l $blksz $dir/b" $dir/a + +echo file2 range entirely beyond EOF +$XFS_IO_PROG -c "swapext -d $(( blksz * (nrblks + 500) )) -s 0 -l $blksz $dir/b" $dir/a + +echo Both ranges entirely beyond EOF +$XFS_IO_PROG -c "swapext -d $(( blksz * (nrblks + 500) )) -s $(( blksz * (nrblks + 500) )) -l $blksz $dir/b" $dir/a + +echo file1 range crossing EOF +$XFS_IO_PROG -c "swapext -s $(( blksz * (nrblks - 1) )) -d 0 -l $((2 * blksz)) $dir/b" $dir/a + +echo file2 range crossing EOF +$XFS_IO_PROG -c "swapext -d $(( blksz * (nrblks - 1) )) -s 0 -l $((2 * blksz)) $dir/b" $dir/a + +echo Both ranges crossing EOF +$XFS_IO_PROG -c "swapext -d $(( blksz * (nrblks - 1) )) -s $(( blksz * (nrblks - 1) )) -l $((blksz * 2)) $dir/b" $dir/a + +echo file1 unaligned EOF to file2 nowhere near EOF +_pwrite_byte 0x58 $((blksz * nrblks)) 37 $dir/a >> $seqres.full +_pwrite_byte 0x59 $((blksz * nrblks)) 37 $dir/b >> $seqres.full +$XFS_IO_PROG -c "swapext -d 0 -s $(( blksz * nrblks )) -l 37 $dir/b" $dir/a + +echo file2 unaligned EOF to file1 nowhere near EOF +$XFS_IO_PROG -c "swapext -s 0 -d $(( blksz * nrblks )) -l 37 $dir/b" $dir/a + +echo Files of unequal length +_pwrite_byte 0x58 $((blksz * nrblks)) $((blksz * 2)) $dir/a >> $seqres.full +_pwrite_byte 0x59 $((blksz * nrblks)) $blksz $dir/b >> $seqres.full +$XFS_IO_PROG -c "swapext $dir/b" $dir/a + +echo Files on different filesystems +_pwrite_byte 0x58 0 $((blksz * nrblks)) $SCRATCH_MNT/c >> $seqres.full +$XFS_IO_PROG -c "swapext $SCRATCH_MNT/c" $dir/a + +echo Files on different mounts +mkdir -p $SCRATCH_MNT/xyz +mount --bind $dir $SCRATCH_MNT/xyz --bind +_pwrite_byte 0x60 0 $((blksz * (nrblks + 2))) $dir/c >> $seqres.full +$XFS_IO_PROG -c "swapext $SCRATCH_MNT/xyz/c" $dir/a +umount $SCRATCH_MNT/xyz + +echo Swapping a file with itself +$XFS_IO_PROG -c "swapext $dir/a" $dir/a + +# success, all done +status=0 +exit diff --git a/tests/generic/1209.out b/tests/generic/1209.out new file mode 100644 index 0000000000..a051ed97d9 --- /dev/null +++ b/tests/generic/1209.out @@ -0,0 +1,33 @@ +QA output created by 1209 +Immutable files +swapext: Operation not permitted +Readonly files +swapext: Bad file descriptor +Directories +swapext: Is a directory +Unaligned ranges +swapext: Invalid argument +file1 range entirely beyond EOF +swapext: Invalid argument +file2 range entirely beyond EOF +swapext: Invalid argument +Both ranges entirely beyond EOF +swapext: Invalid argument +file1 range crossing EOF +swapext: Invalid argument +file2 range crossing EOF +swapext: Invalid argument +Both ranges crossing EOF +swapext: Invalid argument +file1 unaligned EOF to file2 nowhere near EOF +swapext: Invalid argument +file2 unaligned EOF to file1 nowhere near EOF +swapext: Invalid argument +Files of unequal length +swapext: Bad address +Files on different filesystems +swapext: Invalid cross-device link +Files on different mounts +swapext: Invalid cross-device link +Swapping a file with itself +swapext: Invalid argument diff --git a/tests/generic/1210 b/tests/generic/1210 new file mode 100755 index 0000000000..93a325ad7a --- /dev/null +++ b/tests/generic/1210 @@ -0,0 +1,48 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1210 +# +# Make sure swapext honors RLIMIT_FSIZE. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter +. ./common/reflink + +# real QA test starts here +_require_xfs_io_command swapext '-v vfs' +_require_test + +dir=$TEST_DIR/test-$seq +mkdir -p $dir +blksz=65536 +nrblks=64 + +# Create some 4M files to test swapext +_pwrite_byte 0x58 0 $((blksz * nrblks)) $dir/a >> $seqres.full +_pwrite_byte 0x59 0 $((blksz * nrblks)) $dir/b >> $seqres.full +sync +md5sum $dir/a $dir/b | _filter_test_dir + +# Set FSIZE to twice the blocksize (IOWs, 128k) +ulimit -f $(( (blksz * 2) / 512)) +ulimit -a >> $seqres.full + +# Now try to swapext +$XFS_IO_PROG -c "swapext $dir/b" $dir/a +md5sum $dir/a $dir/b | _filter_test_dir + +# success, all done +status=0 +exit diff --git a/tests/generic/1210.out b/tests/generic/1210.out new file mode 100644 index 0000000000..02d41b8838 --- /dev/null +++ b/tests/generic/1210.out @@ -0,0 +1,6 @@ +QA output created by 1210 +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1210/a +901e136269b8d283d311697b7c6dc1f2 TEST_DIR/test-1210/b +swapext: Invalid argument +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1210/a +901e136269b8d283d311697b7c6dc1f2 TEST_DIR/test-1210/b diff --git a/tests/generic/1211 b/tests/generic/1211 new file mode 100755 index 0000000000..f7b8a8d280 --- /dev/null +++ b/tests/generic/1211 @@ -0,0 +1,105 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1211 +# +# Test atomic file replacement when (a) the length is the same; (b) the length +# is different; and (c) someone modifies the original file and we need to +# cancel the update. The staging file is created empty, which implies that the +# caller wants a full file replacement. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter + +# real QA test starts here +_require_xfs_io_command swapext '-v vfs' +_require_xfs_io_command startupdate '-e' +_require_test + +filesnap() { + echo "$1" + md5sum $2 | _filter_test_dir +} + +mkfile() { + rm -f $dir/a + _pwrite_byte 0x58 0 $((blksz * nrblks)) $dir/a >> $seqres.full + sync +} + +dir=$TEST_DIR/test-$seq +mkdir -p $dir +blksz=65536 +nrblks=64 + +# Use the atomic file update staging prototype in xfs_io to update a file. +mkfile +filesnap "before commit" $dir/a + +$XFS_IO_PROG \ + -c 'startupdate -e' \ + -c "pwrite -S 0x60 0 $((blksz * nrblks))" \ + -c 'commitupdate -q' \ + "$dir/a" 2>&1 | _filter_xfs_io | _filter_test_dir + +filesnap "after commit" $dir/a +echo + +# Use the atomic file updates to replace a file with a shorter file. +mkfile +filesnap "before shorten commit" $dir/a + +$XFS_IO_PROG \ + -c 'startupdate -e' \ + -c 'pwrite -S 0x60 0 55k' \ + -c 'commitupdate -q' \ + "$dir/a" 2>&1 | _filter_xfs_io | _filter_test_dir + +filesnap "after shorten commit" $dir/a +echo + +# Use the atomic file updates to replace a file with a longer file. +mkfile +filesnap "before lengthen commit" $dir/a + +$XFS_IO_PROG \ + -c 'startupdate -e' \ + -c "pwrite -S 0x60 0 $(( (blksz * nrblks) + 37373 ))" \ + -c 'commitupdate -q' \ + "$dir/a" 2>&1 | _filter_xfs_io | _filter_test_dir + +filesnap "after lengthen commit" $dir/a +echo + +# Now try the update but with the A file open separately so that we clobber +# mtime and fail the update. +mkfile +filesnap "before fail commit" $dir/a + +$XFS_IO_PROG \ + -c "open $dir/a" \ + -c 'startupdate -e ' \ + -c 'pwrite -S 0x58 44k 55k -b 1m' \ + -c 'file 0' \ + -c 'close' \ + -c 'pwrite -S 0x61 22k 11k -b 1m' \ + -c 'commitupdate -q' \ + "$dir/a" 2>&1 | _filter_xfs_io | _filter_test_dir + +filesnap "after fail commit" $dir/a +echo + +# success, all done +status=0 +exit diff --git a/tests/generic/1211.out b/tests/generic/1211.out new file mode 100644 index 0000000000..a149de198f --- /dev/null +++ b/tests/generic/1211.out @@ -0,0 +1,40 @@ +QA output created by 1211 +before commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1211/a +wrote 4194304/4194304 bytes at offset 0 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Committed updates to 'TEST_DIR/test-1211/a'. +after commit +0558063c531ca7c7864fc5a4923f7144 TEST_DIR/test-1211/a + +before shorten commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1211/a +wrote 56320/56320 bytes at offset 0 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Committed updates to 'TEST_DIR/test-1211/a'. +after shorten commit +52353039d89c5f2b76b9003464e5276a TEST_DIR/test-1211/a + +before lengthen commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1211/a +wrote 4231677/4231677 bytes at offset 0 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Committed updates to 'TEST_DIR/test-1211/a'. +after lengthen commit +1839e7c6bf616160dc51b12179db2642 TEST_DIR/test-1211/a + +before fail commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1211/a +committing update: Device or resource busy +wrote 56320/56320 bytes at offset 45056 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 56320/56320 bytes at offset 45056 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +[000] TEST_DIR/test-1211/a (xfs,non-sync,non-direct,read-write) + 001 TEST_DIR/test-1211/a (fileupdate) (xfs,non-sync,non-direct,read-write) +[000] TEST_DIR/test-1211/a (fileupdate) (xfs,non-sync,non-direct,read-write) +wrote 11264/11264 bytes at offset 22528 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +after fail commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1211/a + diff --git a/tests/generic/1212 b/tests/generic/1212 new file mode 100755 index 0000000000..c6599e3a35 --- /dev/null +++ b/tests/generic/1212 @@ -0,0 +1,58 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1212 +# +# Stress testing with a lot of extents. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter + +# real QA test starts here +_require_xfs_io_command swapext '-v vfs' +_require_test_program punch-alternating +_require_test + +dir=$TEST_DIR/test-$seq +mkdir -p $dir +blksz=$(_get_file_block_size $TEST_DIR) +nrblks=$((LOAD_FACTOR * 100000)) + +_require_fs_space $TEST_DIR $(( (2 * blksz * nrblks) / 1024 )) + +# Create some big swiss cheese files to test swapext with a lot of extents +_pwrite_byte 0x58 0 $((blksz * nrblks)) $dir/a >> $seqres.full +$here/src/punch-alternating $dir/a +_pwrite_byte 0x59 0 $((blksz * nrblks)) $dir/b >> $seqres.full +$here/src/punch-alternating -o 1 $dir/b +filefrag -v $dir/a $dir/b >> $seqres.full + +# Now try to swapext +md5_a="$(md5sum < $dir/a)" +md5_b="$(md5sum < $dir/b)" +date >> $seqres.full +$XFS_IO_PROG -c "swapext $dir/b" $dir/a +date >> $seqres.full + +echo "md5_a=$md5_a" >> $seqres.full +echo "md5_b=$md5_b" >> $seqres.full +md5sum $dir/a $dir/b >> $seqres.full + +test "$(md5sum < $dir/b)" = "$md5_a" || echo "file b does not match former a" +test "$(md5sum < $dir/a)" = "$md5_b" || echo "file a does not match former b" + +echo "Silence is golden!" +# success, all done +status=0 +exit diff --git a/tests/generic/1212.out b/tests/generic/1212.out new file mode 100644 index 0000000000..fb775977ca --- /dev/null +++ b/tests/generic/1212.out @@ -0,0 +1,2 @@ +QA output created by 1212 +Silence is golden! diff --git a/tests/generic/1213 b/tests/generic/1213 new file mode 100755 index 0000000000..d466263a9d --- /dev/null +++ b/tests/generic/1213 @@ -0,0 +1,126 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1213 +# +# Test non-root atomic file updates when (a) the file contents are cloned into +# the staging file; and (b) when the staging file is created empty. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter +. ./common/reflink + +# real QA test starts here +_require_xfs_io_command startupdate +_require_test_reflink +_require_test +_require_user + +filesnap() { + echo "$1" + md5sum $2 | _filter_test_dir +} + +mkfile() { + rm -f $dir/a + _pwrite_byte 0x58 0 $((blksz * nrblks)) $dir/a >> $seqres.full + chown $qa_user $dir/a $dir/ + sync +} + +dir=$TEST_DIR/test-$seq +mkdir -p $dir +blksz=65536 +nrblks=64 + +# Use the atomic file update staging prototype in xfs_io to update a file. +mkfile +filesnap "before commit" $dir/a + +cmd="$XFS_IO_PROG \ + -c 'startupdate' \ + -c 'pwrite -S 0x60 44k 55k -b 1m' \ + -c 'commitupdate -q' \ + \"$dir/a\"" +su -s /bin/bash -c "$cmd" $qa_user 2>&1 | _filter_xfs_io | _filter_test_dir + +filesnap "after commit" $dir/a +echo + +# Use the atomic file updates to replace a file with a shorter file. +mkfile +filesnap "before shorten commit" $dir/a + +cmd="$XFS_IO_PROG \ + -c 'startupdate' \ + -c 'truncate 55k' \ + -c 'pwrite -S 0x60 0 55k' \ + -c 'commitupdate -q' \ + \"$dir/a\"" +su -s /bin/bash -c "$cmd" $qa_user 2>&1 | _filter_xfs_io | _filter_test_dir + +filesnap "after shorten commit" $dir/a +echo + +# Use the atomic file updates to replace a file with a longer file. +mkfile +filesnap "before lengthen commit" $dir/a + +cmd="$XFS_IO_PROG \ + -c 'startupdate' \ + -c \"pwrite -S 0x60 0 $(( (blksz * nrblks) + 37373 ))\" \ + -c 'commitupdate -q' \ + \"$dir/a\"" +su -s /bin/bash -c "$cmd" $qa_user 2>&1 | _filter_xfs_io | _filter_test_dir + +filesnap "after lengthen commit" $dir/a +echo + +# Use the atomic file update staging prototype in xfs_io to cancel updating a +# file. +mkfile +filesnap "before cancel" $dir/a + +cmd="$XFS_IO_PROG \ + -c 'startupdate' \ + -c 'pwrite -S 0x60 44k 55k -b 1m' \ + -c 'cancelupdate' \ + \"$dir/a\"" +su -s /bin/bash -c "$cmd" $qa_user 2>&1 | _filter_xfs_io | _filter_test_dir + +filesnap "after cancel" $dir/a +echo + +# Now try the update but with the A file open separately so that we clobber +# mtime and fail the update. +mkfile +filesnap "before fail commit" $dir/a + +cmd="$XFS_IO_PROG \ + -c \"open $dir/a\" \ + -c 'startupdate' \ + -c 'pwrite -S 0x58 44k 55k -b 1m' \ + -c 'file 0' \ + -c 'close' \ + -c 'pwrite -S 0x61 22k 11k -b 1m' \ + -c 'commitupdate -q' \ + \"$dir/a\"" +su -s /bin/bash -c "$cmd" $qa_user 2>&1 | _filter_xfs_io | _filter_test_dir + +filesnap "after fail commit" $dir/a +echo + +# success, all done +status=0 +exit diff --git a/tests/generic/1213.out b/tests/generic/1213.out new file mode 100644 index 0000000000..b5a140560d --- /dev/null +++ b/tests/generic/1213.out @@ -0,0 +1,48 @@ +QA output created by 1213 +before commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1213/a +wrote 56320/56320 bytes at offset 45056 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Committed updates to 'TEST_DIR/test-1213/a'. +after commit +bedbd22b58a680219a1225353f6195fa TEST_DIR/test-1213/a + +before shorten commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1213/a +wrote 56320/56320 bytes at offset 0 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Committed updates to 'TEST_DIR/test-1213/a'. +after shorten commit +52353039d89c5f2b76b9003464e5276a TEST_DIR/test-1213/a + +before lengthen commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1213/a +wrote 4231677/4231677 bytes at offset 0 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Committed updates to 'TEST_DIR/test-1213/a'. +after lengthen commit +1839e7c6bf616160dc51b12179db2642 TEST_DIR/test-1213/a + +before cancel +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1213/a +wrote 56320/56320 bytes at offset 45056 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +Cancelled updates to 'TEST_DIR/test-1213/a'. +after cancel +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1213/a + +before fail commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1213/a +committing update: Device or resource busy +wrote 56320/56320 bytes at offset 45056 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 56320/56320 bytes at offset 45056 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +[000] TEST_DIR/test-1213/a (xfs,non-sync,non-direct,read-write) + 001 TEST_DIR/test-1213/a (fileupdate) (xfs,non-sync,non-direct,read-write) +[000] TEST_DIR/test-1213/a (fileupdate) (xfs,non-sync,non-direct,read-write) +wrote 11264/11264 bytes at offset 22528 +XXX Bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +after fail commit +d712f003e9d467e063cda1baf319b928 TEST_DIR/test-1213/a + diff --git a/tests/generic/1214 b/tests/generic/1214 new file mode 100755 index 0000000000..0cacc57e9c --- /dev/null +++ b/tests/generic/1214 @@ -0,0 +1,63 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1214 +# +# Test swapext with the fsync flag flushes everything to disk before the call +# returns. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter +. ./common/reflink + +# real QA test starts here +_require_test_program "punch-alternating" +_require_xfs_io_command swapext '-v vfs -a' +_require_scratch +_require_scratch_shutdown + +_scratch_mkfs >> $seqres.full +_scratch_mount + +_pwrite_byte 0x58 0 2m $SCRATCH_MNT/a >> $seqres.full +_pwrite_byte 0x59 0 2m $SCRATCH_MNT/b >> $seqres.full +$here/src/punch-alternating $SCRATCH_MNT/a +$here/src/punch-alternating $SCRATCH_MNT/b + +old_a=$(md5sum $SCRATCH_MNT/a | awk '{print $1}') +old_b=$(md5sum $SCRATCH_MNT/b | awk '{print $1}') +echo "md5 a: $old_a md5 b: $old_b" >> $seqres.full + +od -tx1 -Ad -c $SCRATCH_MNT/a > /tmp/a0 +od -tx1 -Ad -c $SCRATCH_MNT/b > /tmp/b0 + +echo swap >> $seqres.full +$XFS_IO_PROG -c "swapext -v vfs -a -e -f -u $SCRATCH_MNT/a" $SCRATCH_MNT/b +_scratch_shutdown +_scratch_cycle_mount + +new_a=$(md5sum $SCRATCH_MNT/a | awk '{print $1}') +new_b=$(md5sum $SCRATCH_MNT/b | awk '{print $1}') +echo "md5 a: $new_a md5 b: $new_b" >> $seqres.full + +test $old_a = $new_b || echo "scratch file B doesn't match old file A" +test $old_b = $new_a || echo "scratch file A doesn't match old file B" + +od -tx1 -Ad -c $SCRATCH_MNT/a > /tmp/a1 +od -tx1 -Ad -c $SCRATCH_MNT/b > /tmp/b1 + +# success, all done +echo Silence is golden +status=0 +exit diff --git a/tests/generic/1214.out b/tests/generic/1214.out new file mode 100644 index 0000000000..a529e42333 --- /dev/null +++ b/tests/generic/1214.out @@ -0,0 +1,2 @@ +QA output created by 1214 +Silence is golden diff --git a/tests/generic/1215 b/tests/generic/1215 new file mode 100755 index 0000000000..28eb8356d8 --- /dev/null +++ b/tests/generic/1215 @@ -0,0 +1,70 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1215 +# +# Test swapext with the dry run flag doesn't change anything. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter +. ./common/reflink + +# real QA test starts here +_require_test_program "punch-alternating" +_require_xfs_io_command swapext '-v vfs' +_require_scratch + +_scratch_mkfs >> $seqres.full +_scratch_mount + +_pwrite_byte 0x58 0 1m $SCRATCH_MNT/a >> $seqres.full +_pwrite_byte 0x59 0 2m $SCRATCH_MNT/b >> $seqres.full +$XFS_IO_PROG -c 'truncate 2m' $SCRATCH_MNT/a +$here/src/punch-alternating $SCRATCH_MNT/a +$here/src/punch-alternating $SCRATCH_MNT/b + +old_a=$(md5sum $SCRATCH_MNT/a | awk '{print $1}') +old_b=$(md5sum $SCRATCH_MNT/b | awk '{print $1}') +echo "md5 a: $old_a md5 b: $old_b" >> $seqres.full + +# Test swapext with the -n option, which will do all the input parameter +# checking and return 0 without changing anything. +echo dry run swap >> $seqres.full +$XFS_IO_PROG -c "swapext -v vfs -n -f -u $SCRATCH_MNT/a" $SCRATCH_MNT/b +_scratch_cycle_mount + +new_a=$(md5sum $SCRATCH_MNT/a | awk '{print $1}') +new_b=$(md5sum $SCRATCH_MNT/b | awk '{print $1}') +echo "md5 a: $new_a md5 b: $new_b" >> $seqres.full + +test $old_a = $new_a || echo "scratch file A should not have swapped" +test $old_b = $new_b || echo "scratch file B should not have swapped" + +# Do it again, but without the -n option, to prove that we can actually +# swap the file contents. +echo actual swap >> $seqres.full +$XFS_IO_PROG -c "swapext -v vfs -f -u $SCRATCH_MNT/a" $SCRATCH_MNT/b +_scratch_cycle_mount + +new_a=$(md5sum $SCRATCH_MNT/a | awk '{print $1}') +new_b=$(md5sum $SCRATCH_MNT/b | awk '{print $1}') +echo "md5 a: $new_a md5 b: $new_b" >> $seqres.full + +test $old_a = $new_b || echo "scratch file A should have swapped" +test $old_b = $new_a || echo "scratch file B should have swapped" + +# success, all done +echo Silence is golden +status=0 +exit diff --git a/tests/generic/1215.out b/tests/generic/1215.out new file mode 100644 index 0000000000..f68a8e6998 --- /dev/null +++ b/tests/generic/1215.out @@ -0,0 +1,2 @@ +QA output created by 1215 +Silence is golden diff --git a/tests/xfs/1208 b/tests/xfs/1208 new file mode 100755 index 0000000000..3106a4036c --- /dev/null +++ b/tests/xfs/1208 @@ -0,0 +1,62 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1208 +# +# Make sure an atomic swapext actually runs to completion even if we shut +# down the filesystem midway through. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_fs xfs +_require_xfs_io_command swapext '-v vfs -a' +_require_test_program "punch-alternating" +_require_xfs_io_command startupdate +_require_xfs_io_error_injection "bmap_finish_one" +_require_test + +filesnap() { + echo "$1" + md5sum $dir/a $dir/b $dir/c | _filter_test_dir +} + +dir=$TEST_DIR/test-$seq +mkdir -p $dir +blksz=65536 +nrblks=137 + +# Create two files to swap, and try to fragment the first file. +rm -f $dir/a +_pwrite_byte 0x58 0 $((blksz * nrblks)) $dir/a >> $seqres.full +$here/src/punch-alternating $dir/a +_pwrite_byte 0x59 0 $((blksz * nrblks)) $dir/b >> $seqres.full +_pwrite_byte 0x59 0 $((blksz * nrblks)) $dir/c >> $seqres.full +_pwrite_byte 0x58 0 $((blksz * nrblks)) $dir/a >> $seqres.full +sync + +# Inject a bmap error and trigger it via swapext. +filesnap "before commit" +$XFS_IO_PROG -x -c 'inject bmap_finish_one' -c "swapext $dir/b" $dir/a + +# Check the file afterwards. +_test_cycle_mount +filesnap "after commit" + +# success, all done +status=0 +exit diff --git a/tests/xfs/1208.out b/tests/xfs/1208.out new file mode 100644 index 0000000000..b6aa1b6231 --- /dev/null +++ b/tests/xfs/1208.out @@ -0,0 +1,10 @@ +QA output created by 1208 +before commit +c7221b1494117327570a0958b0abca51 TEST_DIR/test-1208/a +30cc2b6b307081e10972317013efb0f3 TEST_DIR/test-1208/b +30cc2b6b307081e10972317013efb0f3 TEST_DIR/test-1208/c +swapext: Input/output error +after commit +30cc2b6b307081e10972317013efb0f3 TEST_DIR/test-1208/a +c7221b1494117327570a0958b0abca51 TEST_DIR/test-1208/b +30cc2b6b307081e10972317013efb0f3 TEST_DIR/test-1208/c From patchwork Wed Mar 1 02:59:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13155528 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CBE27C7EE31 for ; Wed, 1 Mar 2023 02:59:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229718AbjCAC7b (ORCPT ); Tue, 28 Feb 2023 21:59:31 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39968 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229600AbjCAC7a (ORCPT ); Tue, 28 Feb 2023 21:59:30 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3E8E61C32C; Tue, 28 Feb 2023 18:59:28 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id B08EB611F3; Wed, 1 Mar 2023 02:59:27 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 199F2C433EF; Wed, 1 Mar 2023 02:59:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1677639567; bh=VD29bY+us+j3LFFtFzU+z2TI0TNWl6A+pxU08EReyug=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=CkFToiVZUXQbmQBYSed8NmKMbw8WPzwu1C76344cOSZzObVTRIF+mCF9leoONX3iT y674CMpsdrwnjiLUiTEAZJMEb7sqd5tPydWnEQF+JSK5RRAY2sTaBIElkjTwuHQp0Y i4G39OJNSDHbfoTrMkxp16lPWCW5YRWrhytNOaFH315vq1nR/vfpOlA1WJMRVhIu03 lMp9dmPzPpk5NEWB+PzYjafdGI6LLAp2/RO2u5H3krvi4JVE1G5fJRK4054X5OKtSs 0coZxIXxGFgVkRXZQ5WY4f2avAN0QIxPf5D3+OGupTi4x0pW7DtO23Mj6kPvByVWqZ 7cap2ISUcytGA== Subject: [PATCH 4/7] generic, xfs: test scatter-gather atomic file updates From: "Darrick J. Wong" To: djwong@kernel.org, zlang@redhat.com Cc: linux-xfs@vger.kernel.org, fstests@vger.kernel.org, guan@eryu.me Date: Tue, 28 Feb 2023 18:59:26 -0800 Message-ID: <167763956666.3796922.871998280981893774.stgit@magnolia> In-Reply-To: <167763954409.3796922.11086772690906428270.stgit@magnolia> References: <167763954409.3796922.11086772690906428270.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Make sure that FILE_SWAP_RANGE_SKIP_FILE1_HOLES does what we want it to do -- provide a means to implement scatter-gather atomic file writes. That means we create a temporary file, write whatever sparse bits to it that we want, and swap the non-hole parts of the temp file. Signed-off-by: Darrick J. Wong --- common/xfs | 19 +++++++++++++++ tests/generic/1216 | 53 ++++++++++++++++++++++++++++++++++++++++++ tests/generic/1216.out | 6 +++++ tests/generic/1217 | 56 ++++++++++++++++++++++++++++++++++++++++++++ tests/generic/1217.out | 4 +++ tests/xfs/1211 | 59 ++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/1211.out | 7 ++++++ tests/xfs/1212 | 61 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/1212.out | 5 ++++ 9 files changed, 270 insertions(+) create mode 100755 tests/generic/1216 create mode 100644 tests/generic/1216.out create mode 100755 tests/generic/1217 create mode 100644 tests/generic/1217.out create mode 100755 tests/xfs/1211 create mode 100644 tests/xfs/1211.out create mode 100755 tests/xfs/1212 create mode 100644 tests/xfs/1212.out diff --git a/common/xfs b/common/xfs index b2328f1549..11e675c0d2 100644 --- a/common/xfs +++ b/common/xfs @@ -1763,3 +1763,22 @@ _scratch_xfs_find_agbtree_height() { return 1 } + +_require_xfs_mkfs_atomicswap() +{ + # atomicswap can be activated on rmap or reflink filesystems. + # reflink is newer (4.9 for reflink vs. 4.8 for rmap) so test that. + _scratch_mkfs_xfs_supported -m reflink=1 >/dev/null 2>&1 || \ + _notrun "mkfs.xfs doesn't have atomicswap dependent features" +} + +_require_xfs_scratch_atomicswap() +{ + _require_xfs_mkfs_atomicswap + _require_scratch + _require_xfs_io_command swapext '-v vfs -a' + _scratch_mkfs -m reflink=1 > /dev/null + _try_scratch_mount || \ + _notrun "atomicswap dependencies not supported by scratch filesystem type: $FSTYP" + _scratch_unmount +} diff --git a/tests/generic/1216 b/tests/generic/1216 new file mode 100755 index 0000000000..802cfe14d4 --- /dev/null +++ b/tests/generic/1216 @@ -0,0 +1,53 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1216 +# +# Test scatter-gather atomic file writes. We create a temporary file, write +# sparsely to it, then use FILE_SWAP_RANGE_SKIP_FILE1_HOLES flag to swap +# atomicallly only the ranges that we wrote. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter + +# real QA test starts here +_require_xfs_io_command swapext '-v vfs -a' +_require_scratch + +_scratch_mkfs >> $seqres.full +_scratch_mount +_require_congruent_file_oplen $SCRATCH_MNT 65536 + +# Create original file +_pwrite_byte 0x58 0 1m $SCRATCH_MNT/a >> $seqres.full + +# Create the donor file +_pwrite_byte 0x59 64k 64k $SCRATCH_MNT/b >> $seqres.full +_pwrite_byte 0x57 768k 64k $SCRATCH_MNT/b >> $seqres.full +$XFS_IO_PROG -c 'truncate 1m' $SCRATCH_MNT/b + +md5sum $SCRATCH_MNT/a | _filter_scratch +md5sum $SCRATCH_MNT/b | _filter_scratch + +# Test swapext. -h means skip holes in /b, and -e means operate to EOF +echo swap | tee -a $seqres.full +$XFS_IO_PROG -c "swapext -v vfs -f -u -h -e -a $SCRATCH_MNT/b" $SCRATCH_MNT/a +_scratch_cycle_mount + +md5sum $SCRATCH_MNT/a | _filter_scratch +md5sum $SCRATCH_MNT/b | _filter_scratch + +# success, all done +status=0 +exit diff --git a/tests/generic/1216.out b/tests/generic/1216.out new file mode 100644 index 0000000000..2b49d5cfa8 --- /dev/null +++ b/tests/generic/1216.out @@ -0,0 +1,6 @@ +QA output created by 1216 +310f146ce52077fcd3308dcbe7632bb2 SCRATCH_MNT/a +c9fb827e2e3e579dc2a733ddad486d1d SCRATCH_MNT/b +swap +e9cbfe8489a68efaa5fcf40cf3106118 SCRATCH_MNT/a +faf8ed02a5b0638096a817abcc6c2127 SCRATCH_MNT/b diff --git a/tests/generic/1217 b/tests/generic/1217 new file mode 100755 index 0000000000..78c49751f7 --- /dev/null +++ b/tests/generic/1217 @@ -0,0 +1,56 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1217 +# +# Test scatter-gather atomic file commits. Use the startupdate command to +# create a temporary file, write sparsely to it, then commitupdate -h to +# perform the scattered update. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter + +# real QA test starts here +_require_xfs_io_command swapext '-v vfs -a' +_require_xfs_io_command startupdate '-e' +_require_scratch + +_scratch_mkfs >> $seqres.full +_scratch_mount +_require_congruent_file_oplen $SCRATCH_MNT 65536 + +# Create original file +_pwrite_byte 0x58 0 1m $SCRATCH_MNT/a >> $seqres.full +sync +md5sum $SCRATCH_MNT/a | _filter_scratch + +# Test atomic scatter-gather file commits. +echo commit | tee -a $seqres.full +$XFS_IO_PROG \ + -c 'bmap -elpv' \ + -c 'startupdate -e' \ + -c 'truncate 1m' \ + -c 'pwrite -S 0x59 64k 64k' \ + -c 'pwrite -S 0x57 768k 64k' \ + -c 'bmap -elpv' \ + -c 'commitupdate -h -k' \ + -c 'bmap -elpv' \ + $SCRATCH_MNT/a >> $seqres.full +_scratch_cycle_mount + +md5sum $SCRATCH_MNT/a | _filter_scratch + +# success, all done +status=0 +exit diff --git a/tests/generic/1217.out b/tests/generic/1217.out new file mode 100644 index 0000000000..73bf89895d --- /dev/null +++ b/tests/generic/1217.out @@ -0,0 +1,4 @@ +QA output created by 1217 +310f146ce52077fcd3308dcbe7632bb2 SCRATCH_MNT/a +commit +e9cbfe8489a68efaa5fcf40cf3106118 SCRATCH_MNT/a diff --git a/tests/xfs/1211 b/tests/xfs/1211 new file mode 100755 index 0000000000..6297b8ad67 --- /dev/null +++ b/tests/xfs/1211 @@ -0,0 +1,59 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1211 +# +# Test scatter-gather atomic file writes. We create a temporary file, write +# sparsely to it, then use FILE_SWAP_RANGE_SKIP_FILE1_HOLES flag to swap +# atomicallly only the ranges that we wrote. Inject an error so that we can +# test that log recovery finishes the swap. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter +. ./common/inject + +# real QA test starts here +_supported_fs xfs +_require_xfs_io_command swapext '-v vfs -a' +_require_xfs_scratch_atomicswap +_require_xfs_io_error_injection "bmap_finish_one" + +_scratch_mkfs >> $seqres.full +_scratch_mount +_require_congruent_file_oplen $SCRATCH_MNT 65536 + +# Create original file +_pwrite_byte 0x58 0 1m $SCRATCH_MNT/a >> $seqres.full + +# Create the donor file +_pwrite_byte 0x59 64k 64k $SCRATCH_MNT/b >> $seqres.full +_pwrite_byte 0x57 768k 64k $SCRATCH_MNT/b >> $seqres.full +$XFS_IO_PROG -c 'truncate 1m' $SCRATCH_MNT/b +sync + +md5sum $SCRATCH_MNT/a | _filter_scratch +md5sum $SCRATCH_MNT/b | _filter_scratch + +# Test swapext. -h means skip holes in /b, and -e means operate to EOF +echo swap | tee -a $seqres.full +$XFS_IO_PROG -x -c 'inject bmap_finish_one' \ + -c "swapext -v vfs -f -u -h -e -a $SCRATCH_MNT/b" $SCRATCH_MNT/a +_scratch_cycle_mount + +md5sum $SCRATCH_MNT/a | _filter_scratch +md5sum $SCRATCH_MNT/b | _filter_scratch + +# success, all done +status=0 +exit diff --git a/tests/xfs/1211.out b/tests/xfs/1211.out new file mode 100644 index 0000000000..19412c21a1 --- /dev/null +++ b/tests/xfs/1211.out @@ -0,0 +1,7 @@ +QA output created by 1211 +310f146ce52077fcd3308dcbe7632bb2 SCRATCH_MNT/a +c9fb827e2e3e579dc2a733ddad486d1d SCRATCH_MNT/b +swap +swapext: Input/output error +e9cbfe8489a68efaa5fcf40cf3106118 SCRATCH_MNT/a +faf8ed02a5b0638096a817abcc6c2127 SCRATCH_MNT/b diff --git a/tests/xfs/1212 b/tests/xfs/1212 new file mode 100755 index 0000000000..d2292d65a2 --- /dev/null +++ b/tests/xfs/1212 @@ -0,0 +1,61 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test No. 1212 +# +# Test scatter-gather atomic file commits. Use the startupdate command to +# create a temporary file, write sparsely to it, then commitupdate -h to +# perform the scattered update. Inject an error so that we can test that log +# recovery finishes the swap. + +. ./common/preamble +_begin_fstest auto quick fiexchange swapext + +# Override the default cleanup function. +_cleanup() +{ + cd / + rm -r -f $tmp.* $dir +} + +# Import common functions. +. ./common/filter +. ./common/inject + +# real QA test starts here +_supported_fs xfs +_require_xfs_io_command swapext '-v vfs -a' +_require_xfs_io_command startupdate '-e' +_require_xfs_scratch_atomicswap +_require_xfs_io_error_injection "bmap_finish_one" + +_scratch_mkfs >> $seqres.full +_scratch_mount + +# Create original file +_pwrite_byte 0x58 0 1m $SCRATCH_MNT/a >> $seqres.full +sync +md5sum $SCRATCH_MNT/a | _filter_scratch + +# Test atomic scatter-gather file commits. +echo commit | tee -a $seqres.full +$XFS_IO_PROG -x \ + -c 'bmap -elpv' \ + -c 'startupdate -e' \ + -c 'truncate 1m' \ + -c 'pwrite -S 0x59 64k 64k' \ + -c 'pwrite -S 0x57 768k 64k' \ + -c 'sync' \ + -c 'bmap -elpv' \ + -c 'inject bmap_finish_one' \ + -c 'commitupdate -h -k' \ + $SCRATCH_MNT/a >> $seqres.full +_scratch_cycle_mount + +$XFS_IO_PROG -c 'bmap -elpv' $SCRATCH_MNT/a >> $seqres.full +md5sum $SCRATCH_MNT/a | _filter_scratch + +# success, all done +status=0 +exit diff --git a/tests/xfs/1212.out b/tests/xfs/1212.out new file mode 100644 index 0000000000..29718e2024 --- /dev/null +++ b/tests/xfs/1212.out @@ -0,0 +1,5 @@ +QA output created by 1212 +310f146ce52077fcd3308dcbe7632bb2 SCRATCH_MNT/a +commit +committing update: Input/output error +e9cbfe8489a68efaa5fcf40cf3106118 SCRATCH_MNT/a From patchwork Wed Mar 1 02:59:32 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13155530 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EA9DCC6FA8E for ; Wed, 1 Mar 2023 02:59:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229724AbjCAC7k (ORCPT ); Tue, 28 Feb 2023 21:59:40 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40160 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229668AbjCAC7j (ORCPT ); Tue, 28 Feb 2023 21:59:39 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [145.40.68.75]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 904276E97; Tue, 28 Feb 2023 18:59:35 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id 0F867B80ED1; Wed, 1 Mar 2023 02:59:34 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id B5C64C433D2; Wed, 1 Mar 2023 02:59:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1677639572; bh=lcRbbT4hYzL+E4ZZlSfVwqApsVGMxkx0njhBLIOXB8g=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=t+3d4heBvDGwr+LjIqPH4kwcmJ1+k3MTH9CHN3rIbFVisumU4gjOJh7N7YmW7Zrl0 hVaSV2xEVfjnsR1PaOZXciYEUwma5AJP+M7duzKEc6Ai/tOBwWdZ/wIbv1w/YulIqV 0chVwNzDSwVJc/Q+IOTTZdKBCFk6NAyYoe70Ek4Gu2KWvoC/Tb78k7ohJNSY3G2QRN lJp6VEdGG3ICyHMuiPIDrHn8SlrO2wGl0aGZeWojyQzYaWLdXeI66QtBCqFj3D7YSo z30Vz68PZfdEgZOsRR7lINBFicj57kmnmJylQGOHU2ImhIQbZWUbCMddExfbAfGudX LPdp09o8GaqWg== Subject: [PATCH 5/7] generic: test that file privilege gets dropped with FIEXCHANGE_RANGE From: "Darrick J. Wong" To: djwong@kernel.org, zlang@redhat.com Cc: linux-xfs@vger.kernel.org, fstests@vger.kernel.org, guan@eryu.me Date: Tue, 28 Feb 2023 18:59:32 -0800 Message-ID: <167763957229.3796922.2048519729546749794.stgit@magnolia> In-Reply-To: <167763954409.3796922.11086772690906428270.stgit@magnolia> References: <167763954409.3796922.11086772690906428270.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Make sure that we clear the suid and sgid bits and capabilities during a FIEXCHANGE_RANGE call just like we would for a regular file write. Signed-off-by: Darrick J. Wong --- tests/generic/1218 | 115 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/1218.out | 49 ++++++++++++++++++++ tests/generic/1219 | 83 +++++++++++++++++++++++++++++++++++ tests/generic/1219.out | 17 +++++++ 4 files changed, 264 insertions(+) create mode 100755 tests/generic/1218 create mode 100644 tests/generic/1218.out create mode 100755 tests/generic/1219 create mode 100755 tests/generic/1219.out diff --git a/tests/generic/1218 b/tests/generic/1218 new file mode 100755 index 0000000000..e6c170351e --- /dev/null +++ b/tests/generic/1218 @@ -0,0 +1,115 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test 1218 +# +# Functional test for dropping suid and sgid bits as part of an atomic file +# commit. +# +. ./common/preamble +_begin_fstest auto fiexchange swapext quick + +# Override the default cleanup function. +# _cleanup() +# { +# cd / +# rm -r -f $tmp.* +# } + +# Import common functions. +. ./common/filter + +# real QA test starts here + +# Modify as appropriate. +_supported_fs generic +_require_user +_require_xfs_io_command swapext '-v vfs -a' +_require_xfs_io_command startupdate +_require_scratch + +_scratch_mkfs >> $seqres.full +_scratch_mount +_require_congruent_file_oplen $SCRATCH_MNT 1048576 +chmod a+rw $SCRATCH_MNT/ + +setup_testfile() { + rm -f $SCRATCH_MNT/a + _pwrite_byte 0x58 0 1m $SCRATCH_MNT/a >> $seqres.full + sync +} + +commit_and_check() { + local user="$1" + + md5sum $SCRATCH_MNT/a | _filter_scratch + stat -c '%a %A %n' $SCRATCH_MNT/a | _filter_scratch + + local cmd="$XFS_IO_PROG -c 'startupdate' -c 'pwrite -S 0x57 0 1m' -c 'commitupdate' $SCRATCH_MNT/a" + if [ -n "$user" ]; then + su - "$user" -c "$cmd" >> $seqres.full + else + $SHELL -c "$cmd" >> $seqres.full + fi + + _scratch_cycle_mount + md5sum $SCRATCH_MNT/a | _filter_scratch + stat -c '%a %A %n' $SCRATCH_MNT/a | _filter_scratch + + # Blank line in output + echo +} + +# Commit to a non-exec file by an unprivileged user clears suid but leaves +# sgid. +echo "Test 1 - qa_user, non-exec file" +setup_testfile +chmod a+rws $SCRATCH_MNT/a +commit_and_check "$qa_user" + +# Commit to a group-exec file by an unprivileged user clears suid and sgid. +echo "Test 2 - qa_user, group-exec file" +setup_testfile +chmod g+x,a+rws $SCRATCH_MNT/a +commit_and_check "$qa_user" + +# Commit to a user-exec file by an unprivileged user clears suid but not sgid. +echo "Test 3 - qa_user, user-exec file" +setup_testfile +chmod u+x,a+rws,g-x $SCRATCH_MNT/a +commit_and_check "$qa_user" + +# Commit to a all-exec file by an unprivileged user clears suid and sgid. +echo "Test 4 - qa_user, all-exec file" +setup_testfile +chmod a+rwxs $SCRATCH_MNT/a +commit_and_check "$qa_user" + +# Commit to a non-exec file by root leaves suid and sgid. +echo "Test 5 - root, non-exec file" +setup_testfile +chmod a+rws $SCRATCH_MNT/a +commit_and_check + +# Commit to a group-exec file by root leaves suid and sgid. +echo "Test 6 - root, group-exec file" +setup_testfile +chmod g+x,a+rws $SCRATCH_MNT/a +commit_and_check + +# Commit to a user-exec file by root leaves suid and sgid. +echo "Test 7 - root, user-exec file" +setup_testfile +chmod u+x,a+rws,g-x $SCRATCH_MNT/a +commit_and_check + +# Commit to a all-exec file by root leaves suid and sgid. +echo "Test 8 - root, all-exec file" +setup_testfile +chmod a+rwxs $SCRATCH_MNT/a +commit_and_check + +# success, all done +status=0 +exit diff --git a/tests/generic/1218.out b/tests/generic/1218.out new file mode 100644 index 0000000000..8f4469aad4 --- /dev/null +++ b/tests/generic/1218.out @@ -0,0 +1,49 @@ +QA output created by 1218 +Test 1 - qa_user, non-exec file +310f146ce52077fcd3308dcbe7632bb2 SCRATCH_MNT/a +6666 -rwSrwSrw- SCRATCH_MNT/a +3784de23efab7a2074c9ec66901e39e5 SCRATCH_MNT/a +666 -rw-rw-rw- SCRATCH_MNT/a + +Test 2 - qa_user, group-exec file +310f146ce52077fcd3308dcbe7632bb2 SCRATCH_MNT/a +6676 -rwSrwsrw- SCRATCH_MNT/a +3784de23efab7a2074c9ec66901e39e5 SCRATCH_MNT/a +676 -rw-rwxrw- SCRATCH_MNT/a + +Test 3 - qa_user, user-exec file +310f146ce52077fcd3308dcbe7632bb2 SCRATCH_MNT/a +6766 -rwsrwSrw- SCRATCH_MNT/a +3784de23efab7a2074c9ec66901e39e5 SCRATCH_MNT/a +766 -rwxrw-rw- SCRATCH_MNT/a + +Test 4 - qa_user, all-exec file +310f146ce52077fcd3308dcbe7632bb2 SCRATCH_MNT/a +6777 -rwsrwsrwx SCRATCH_MNT/a +3784de23efab7a2074c9ec66901e39e5 SCRATCH_MNT/a +777 -rwxrwxrwx SCRATCH_MNT/a + +Test 5 - root, non-exec file +310f146ce52077fcd3308dcbe7632bb2 SCRATCH_MNT/a +6666 -rwSrwSrw- SCRATCH_MNT/a +3784de23efab7a2074c9ec66901e39e5 SCRATCH_MNT/a +6666 -rwSrwSrw- SCRATCH_MNT/a + +Test 6 - root, group-exec file +310f146ce52077fcd3308dcbe7632bb2 SCRATCH_MNT/a +6676 -rwSrwsrw- SCRATCH_MNT/a +3784de23efab7a2074c9ec66901e39e5 SCRATCH_MNT/a +6676 -rwSrwsrw- SCRATCH_MNT/a + +Test 7 - root, user-exec file +310f146ce52077fcd3308dcbe7632bb2 SCRATCH_MNT/a +6766 -rwsrwSrw- SCRATCH_MNT/a +3784de23efab7a2074c9ec66901e39e5 SCRATCH_MNT/a +6766 -rwsrwSrw- SCRATCH_MNT/a + +Test 8 - root, all-exec file +310f146ce52077fcd3308dcbe7632bb2 SCRATCH_MNT/a +6777 -rwsrwsrwx SCRATCH_MNT/a +3784de23efab7a2074c9ec66901e39e5 SCRATCH_MNT/a +6777 -rwsrwsrwx SCRATCH_MNT/a + diff --git a/tests/generic/1219 b/tests/generic/1219 new file mode 100755 index 0000000000..fe20475058 --- /dev/null +++ b/tests/generic/1219 @@ -0,0 +1,83 @@ +#! /bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2022 Oracle. All Rights Reserved. +# +# FS QA Test 1219 +# +# Functional test for dropping capability bits as part of an atomic file +# commit. +# +. ./common/preamble +_begin_fstest auto fiexchange swapext quick + +# Override the default cleanup function. +# _cleanup() +# { +# cd / +# rm -r -f $tmp.* +# } + +# Import common functions. +. ./common/filter + +# real QA test starts here + +# Modify as appropriate. +_supported_fs generic +_require_user +_require_command "$GETCAP_PROG" getcap +_require_command "$SETCAP_PROG" setcap +_require_xfs_io_command swapext '-v vfs -a' +_require_xfs_io_command startupdate +_require_scratch + +_scratch_mkfs >> $seqres.full +_scratch_mount +_require_congruent_file_oplen $SCRATCH_MNT 1048576 +chmod a+rw $SCRATCH_MNT/ + +setup_testfile() { + rm -f $SCRATCH_MNT/a $SCRATCH_MNT/b + _pwrite_byte 0x58 0 1m $SCRATCH_MNT/a >> $seqres.full + _pwrite_byte 0x57 0 1m $SCRATCH_MNT/b >> $seqres.full + chmod a+rw $SCRATCH_MNT/a $SCRATCH_MNT/b + $SETCAP_PROG cap_setgid,cap_setuid+ep $SCRATCH_MNT/a + sync +} + +commit_and_check() { + local user="$1" + + md5sum $SCRATCH_MNT/a | _filter_scratch + stat -c '%a %A %n' $SCRATCH_MNT/a | _filter_scratch + _getcap -v $SCRATCH_MNT/a | _filter_scratch + + local cmd="$XFS_IO_PROG -c 'startupdate' -c 'pwrite -S 0x57 0 1m' -c 'commitupdate' $SCRATCH_MNT/a" + if [ -n "$user" ]; then + su - "$user" -c "$cmd" >> $seqres.full + else + $SHELL -c "$cmd" >> $seqres.full + fi + + _scratch_cycle_mount + md5sum $SCRATCH_MNT/a | _filter_scratch + stat -c '%a %A %n' $SCRATCH_MNT/a | _filter_scratch + _getcap -v $SCRATCH_MNT/a | _filter_scratch + + # Blank line in output + echo +} + +# Commit by an unprivileged user clears capability bits. +echo "Test 1 - qa_user" +setup_testfile +commit_and_check "$qa_user" + +# Commit by root leaves capability bits. +echo "Test 2 - root" +setup_testfile +commit_and_check + +# success, all done +status=0 +exit diff --git a/tests/generic/1219.out b/tests/generic/1219.out new file mode 100755 index 0000000000..a925b4ec4f --- /dev/null +++ b/tests/generic/1219.out @@ -0,0 +1,17 @@ +QA output created by 1219 +Test 1 - qa_user +310f146ce52077fcd3308dcbe7632bb2 SCRATCH_MNT/a +666 -rw-rw-rw- SCRATCH_MNT/a +SCRATCH_MNT/a cap_setgid,cap_setuid=ep +3784de23efab7a2074c9ec66901e39e5 SCRATCH_MNT/a +666 -rw-rw-rw- SCRATCH_MNT/a +SCRATCH_MNT/a + +Test 2 - root +310f146ce52077fcd3308dcbe7632bb2 SCRATCH_MNT/a +666 -rw-rw-rw- SCRATCH_MNT/a +SCRATCH_MNT/a cap_setgid,cap_setuid=ep +3784de23efab7a2074c9ec66901e39e5 SCRATCH_MNT/a +666 -rw-rw-rw- SCRATCH_MNT/a +SCRATCH_MNT/a + From patchwork Wed Mar 1 02:59:37 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13155531 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6167FC64EC4 for ; Wed, 1 Mar 2023 02:59:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229713AbjCAC7p (ORCPT ); Tue, 28 Feb 2023 21:59:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40260 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229600AbjCAC7o (ORCPT ); Tue, 28 Feb 2023 21:59:44 -0500 Received: from ams.source.kernel.org (ams.source.kernel.org [IPv6:2604:1380:4601:e00::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 12A44C167; Tue, 28 Feb 2023 18:59:41 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ams.source.kernel.org (Postfix) with ESMTPS id A8E80B80ED1; Wed, 1 Mar 2023 02:59:39 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6CE46C433D2; Wed, 1 Mar 2023 02:59:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1677639578; bh=qa/b3NIGennoOuldrWnYpcRzPhz3XfiAsKie+miooy8=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=ADZ1hxpVJ/sPw7DVhzHXtWJyIZp9HoNZJwbS5iiiNu9Pv1HjLMAOXhl90x8Tp86PD IE7opg3HbH8GD7+bRYw9xLZFanreM9sz0/3XjBVV537Ppl5AdLMnxxx97oqqKsY2l7 xZ5OF3qP5UPa8Q/a/OZ67y3Fqv+KG10bIU/BvHmiZD4vl8sIxNRMHf+jLKaobGx9e1 nbzpwyPc3TnpQO2SQzSsG5gtD7ZotLfegYFmO1szWGOnd3n8w6KhA1jdFTWRPSTgzM b0dfHGPwEM4mLflIyT1Dz90Lm6J7QwdM9QCi0/3kJ8ibMC7Ej09Qvczxu3aexNE9XD CFogbrKUYbIxg== Subject: [PATCH 6/7] fsx: support FIEXCHANGE_RANGE From: "Darrick J. Wong" To: djwong@kernel.org, zlang@redhat.com Cc: linux-xfs@vger.kernel.org, fstests@vger.kernel.org, guan@eryu.me Date: Tue, 28 Feb 2023 18:59:37 -0800 Message-ID: <167763957792.3796922.13050029178000320213.stgit@magnolia> In-Reply-To: <167763954409.3796922.11086772690906428270.stgit@magnolia> References: <167763954409.3796922.11086772690906428270.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Upgrade fsx to support exchanging file contents. Signed-off-by: Darrick J. Wong --- configure.ac | 1 include/builddefs.in | 1 ltp/Makefile | 4 + ltp/fsx.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++++- m4/package_libcdev.m4 | 20 ++++++ src/fiexchange.h | 101 +++++++++++++++++++++++++++++++ src/global.h | 6 ++ 7 files changed, 291 insertions(+), 2 deletions(-) create mode 100644 src/fiexchange.h diff --git a/configure.ac b/configure.ac index e92bd6b26d..4687d8a3c0 100644 --- a/configure.ac +++ b/configure.ac @@ -70,6 +70,7 @@ AC_HAVE_SEEK_DATA AC_HAVE_BMV_OF_SHARED AC_HAVE_NFTW AC_HAVE_RLIMIT_NOFILE +AC_HAVE_FIEXCHANGE AC_CHECK_FUNCS([renameat2]) AC_CHECK_FUNCS([reallocarray]) diff --git a/include/builddefs.in b/include/builddefs.in index dab10c968f..969acf0da2 100644 --- a/include/builddefs.in +++ b/include/builddefs.in @@ -72,6 +72,7 @@ HAVE_SEEK_DATA = @have_seek_data@ HAVE_NFTW = @have_nftw@ HAVE_BMV_OF_SHARED = @have_bmv_of_shared@ HAVE_RLIMIT_NOFILE = @have_rlimit_nofile@ +HAVE_FIEXCHANGE = @have_fiexchange@ GCCFLAGS = -funsigned-char -fno-strict-aliasing -Wall diff --git a/ltp/Makefile b/ltp/Makefile index 85f634145c..c2b70d896e 100644 --- a/ltp/Makefile +++ b/ltp/Makefile @@ -36,6 +36,10 @@ ifeq ($(HAVE_COPY_FILE_RANGE),yes) LCFLAGS += -DHAVE_COPY_FILE_RANGE endif +ifeq ($(HAVE_FIEXCHANGE),yes) +LCFLAGS += -DHAVE_FIEXCHANGE +endif + default: depend $(TARGETS) depend: .dep diff --git a/ltp/fsx.c b/ltp/fsx.c index 12c2cc33bf..ee4b8fe45d 100644 --- a/ltp/fsx.c +++ b/ltp/fsx.c @@ -111,6 +111,7 @@ enum { OP_CLONE_RANGE, OP_DEDUPE_RANGE, OP_COPY_RANGE, + OP_EXCHANGE_RANGE, OP_MAX_FULL, /* integrity operations */ @@ -175,6 +176,7 @@ int check_file = 0; /* -X flag enables */ int clone_range_calls = 1; /* -J flag disables */ int dedupe_range_calls = 1; /* -B flag disables */ int copy_range_calls = 1; /* -E flag disables */ +int xchg_range_calls = 1; /* -0 flag disables */ int integrity = 0; /* -i flag */ int fsxgoodfd = 0; int o_direct; /* -Z */ @@ -268,6 +270,7 @@ static const char *op_names[] = { [OP_DEDUPE_RANGE] = "dedupe_range", [OP_COPY_RANGE] = "copy_range", [OP_FSYNC] = "fsync", + [OP_EXCHANGE_RANGE] = "xchg_range", }; static const char *op_name(int operation) @@ -452,6 +455,20 @@ logdump(void) if (overlap) prt("\t******IIII"); break; + case OP_EXCHANGE_RANGE: + prt("XCHG 0x%x thru 0x%x\t(0x%x bytes) to 0x%x thru 0x%x", + lp->args[0], lp->args[0] + lp->args[1] - 1, + lp->args[1], + lp->args[2], lp->args[2] + lp->args[1] - 1); + overlap2 = badoff >= lp->args[2] && + badoff < lp->args[2] + lp->args[1]; + if (overlap && overlap2) + prt("\tXXXX**XXXX"); + else if (overlap) + prt("\tXXXX******"); + else if (overlap2) + prt("\t******XXXX"); + break; case OP_CLONE_RANGE: prt("CLONE 0x%x thru 0x%x\t(0x%x bytes) to 0x%x thru 0x%x", lp->args[0], lp->args[0] + lp->args[1] - 1, @@ -1369,6 +1386,116 @@ do_insert_range(unsigned offset, unsigned length) } #endif +#ifdef FIEXCHANGE_RANGE +static __u64 swap_flags = 0; + +int +test_xchg_range(void) +{ + struct file_xchg_range fsr = { + .file1_fd = fd, + .flags = FILE_XCHG_RANGE_DRY_RUN | swap_flags, + }; + int ret, e; + +retry: + ret = ioctl(fd, FIEXCHANGE_RANGE, &fsr); + e = ret < 0 ? errno : 0; + if (e == EOPNOTSUPP && !(swap_flags & FILE_XCHG_RANGE_NONATOMIC)) { + /* + * If the call fails with atomic mode, try again with non + * atomic mode. + */ + swap_flags = FILE_XCHG_RANGE_NONATOMIC; + fsr.flags |= swap_flags; + goto retry; + } + if (e == EOPNOTSUPP || errno == ENOTTY) { + if (!quiet) + fprintf(stderr, + "main: filesystem does not support " + "exchange range, disabling!\n"); + return 0; + } + + return 1; +} + +void +do_xchg_range(unsigned offset, unsigned length, unsigned dest) +{ + struct file_xchg_range fsr = { + .file1_fd = fd, + .file1_offset = offset, + .file2_offset = dest, + .length = length, + .flags = swap_flags, + }; + void *p; + + if (length == 0) { + if (!quiet && testcalls > simulatedopcount) + prt("skipping zero length exchange range\n"); + log5(OP_EXCHANGE_RANGE, offset, length, dest, FL_SKIPPED); + return; + } + + if ((loff_t)offset >= file_size || (loff_t)dest >= file_size) { + if (!quiet && testcalls > simulatedopcount) + prt("skipping exchange range behind EOF\n"); + log5(OP_EXCHANGE_RANGE, offset, length, dest, FL_SKIPPED); + return; + } + + p = malloc(length); + if (!p) { + if (!quiet && testcalls > simulatedopcount) + prt("skipping exchange range due to ENOMEM\n"); + log5(OP_EXCHANGE_RANGE, offset, length, dest, FL_SKIPPED); + return; + } + + log5(OP_EXCHANGE_RANGE, offset, length, dest, FL_NONE); + + if (testcalls <= simulatedopcount) + goto out_free; + + if ((progressinterval && testcalls % progressinterval == 0) || + (debug && (monitorstart == -1 || monitorend == -1 || + dest <= monitorstart || dest + length <= monitorend))) { + prt("%lu swap\tfrom 0x%x to 0x%x, (0x%x bytes) at 0x%x\n", + testcalls, offset, offset+length, length, dest); + } + + if (ioctl(fd, FIEXCHANGE_RANGE, &fsr) == -1) { + prt("exchange range: 0x%x to 0x%x at 0x%x\n", offset, + offset + length, dest); + prterr("do_xchg_range: FIEXCHANGE_RANGE"); + report_failure(161); + goto out_free; + } + + memcpy(p, good_buf + offset, length); + memcpy(good_buf + offset, good_buf + dest, length); + memcpy(good_buf + dest, p, length); +out_free: + free(p); +} + +#else +int +test_xchg_range(void) +{ + return 0; +} + +void +do_xchg_range(unsigned offset, unsigned length, unsigned dest) +{ + return; +} +#endif + #ifdef FICLONERANGE int test_clone_range(void) @@ -1856,6 +1983,7 @@ static int op_args_count(int operation) { switch (operation) { + case OP_EXCHANGE_RANGE: case OP_CLONE_RANGE: case OP_DEDUPE_RANGE: case OP_COPY_RANGE: @@ -2053,6 +2181,9 @@ test(void) case OP_COPY_RANGE: generate_dest_range(true, maxfilelen, &offset, &size, &offset2); break; + case OP_EXCHANGE_RANGE: + generate_dest_range(false, file_size, &offset, &size, &offset2); + break; } have_op: @@ -2096,6 +2227,12 @@ test(void) goto out; } break; + case OP_EXCHANGE_RANGE: + if (!xchg_range_calls) { + log5(op, offset, size, offset2, FL_SKIPPED); + goto out; + } + break; case OP_CLONE_RANGE: if (!clone_range_calls) { log5(op, offset, size, offset2, FL_SKIPPED); @@ -2180,6 +2317,18 @@ test(void) do_insert_range(offset, size); break; + case OP_EXCHANGE_RANGE: + if (size == 0) { + log5(OP_EXCHANGE_RANGE, offset, size, offset2, FL_SKIPPED); + goto out; + } + if (offset2 + size > maxfilelen) { + log5(OP_EXCHANGE_RANGE, offset, size, offset2, FL_SKIPPED); + goto out; + } + + do_xchg_range(offset, size, offset2); + break; case OP_CLONE_RANGE: if (size == 0) { log5(OP_CLONE_RANGE, offset, size, offset2, FL_SKIPPED); @@ -2294,6 +2443,9 @@ usage(void) #ifdef HAVE_COPY_FILE_RANGE " -E: Do not use copy range calls\n" #endif +#ifdef FIEXCHANGE_RANGE +" -0: Do not use exchange range calls\n" +#endif " -L: fsxLite - no file creations & no file size changes\n\ -N numops: total # operations to do (default infinity)\n\ -O: use oplen (see -o flag) for every op (default random)\n\ @@ -2608,12 +2760,11 @@ main(int argc, char **argv) page_size = getpagesize(); page_mask = page_size - 1; mmap_mask = page_mask; - setvbuf(stdout, (char *)0, _IOLBF, 0); /* line buffered stdout */ while ((ch = getopt_long(argc, argv, - "b:c:dfg:i:j:kl:m:no:p:qr:s:t:w:xyABD:EFJKHzCILN:OP:RS:UWXZ", + "0b:c:dfg:i:j:kl:m:no:p:qr:s:t:w:xyABD:EFJKHzCILN:OP:RS:UWXZ", longopts, NULL)) != EOF) switch (ch) { case 'b': @@ -2747,6 +2898,9 @@ main(int argc, char **argv) case 'I': insert_range_calls = 0; break; + case '0': + xchg_range_calls = 0; + break; case 'J': clone_range_calls = 0; break; @@ -2988,6 +3142,8 @@ main(int argc, char **argv) dedupe_range_calls = test_dedupe_range(); if (copy_range_calls) copy_range_calls = test_copy_range(); + if (xchg_range_calls) + xchg_range_calls = test_xchg_range(); while (numops == -1 || numops--) if (!test()) diff --git a/m4/package_libcdev.m4 b/m4/package_libcdev.m4 index 98572aecd9..b41c087bfb 100644 --- a/m4/package_libcdev.m4 +++ b/m4/package_libcdev.m4 @@ -154,3 +154,23 @@ AC_DEFUN([AC_HAVE_RLIMIT_NOFILE], AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)]) AC_SUBST(have_rlimit_nofile) ]) + +# +# Check if we have a FIEXCHANGE_RANGE ioctl (Linux) +# +AC_DEFUN([AC_HAVE_FIEXCHANGE], + [ AC_MSG_CHECKING([for FIEXCHANGE_RANGE]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([[ +#define _GNU_SOURCE +#include +#include +#include +#include +#include + ]], [[ + struct file_xchg_range fxr; + ioctl(-1, FIEXCHANGE_RANGE, &fxr); + ]])],[have_fiexchange=yes + AC_MSG_RESULT(yes)],[AC_MSG_RESULT(no)]) + AC_SUBST(have_fiexchange) + ]) diff --git a/src/fiexchange.h b/src/fiexchange.h new file mode 100644 index 0000000000..29b3ac0ff5 --- /dev/null +++ b/src/fiexchange.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later WITH Linux-syscall-note */ +/* + * FIEXCHANGE ioctl definitions, to facilitate exchanging parts of files. + * + * Copyright (C) 2022 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + */ +#ifndef _LINUX_FIEXCHANGE_H +#define _LINUX_FIEXCHANGE_H + +#include + +/* + * Exchange part of file1 with part of the file that this ioctl that is being + * called against (which we'll call file2). Filesystems must be able to + * restart and complete the operation even after the system goes down. + */ +struct file_xchg_range { + __s64 file1_fd; + __s64 file1_offset; /* file1 offset, bytes */ + __s64 file2_offset; /* file2 offset, bytes */ + __s64 length; /* bytes to exchange */ + + __u64 flags; /* see FILE_XCHG_RANGE_* below */ + + /* file2 metadata for optional freshness checks */ + __s64 file2_ino; /* inode number */ + __s64 file2_mtime; /* modification time */ + __s64 file2_ctime; /* change time */ + __s32 file2_mtime_nsec; /* mod time, nsec */ + __s32 file2_ctime_nsec; /* change time, nsec */ + + __u64 pad[6]; /* must be zeroes */ +}; + +/* + * Atomic exchange operations are not required. This relaxes the requirement + * that the filesystem must be able to complete the operation after a crash. + */ +#define FILE_XCHG_RANGE_NONATOMIC (1 << 0) + +/* + * Check that file2's inode number, mtime, and ctime against the values + * provided, and return -EBUSY if there isn't an exact match. + */ +#define FILE_XCHG_RANGE_FILE2_FRESH (1 << 1) + +/* + * Check that the file1's length is equal to file1_offset + length, and that + * file2's length is equal to file2_offset + length. Returns -EDOM if there + * isn't an exact match. + */ +#define FILE_XCHG_RANGE_FULL_FILES (1 << 2) + +/* + * Exchange file data all the way to the ends of both files, and then exchange + * the file sizes. This flag can be used to replace a file's contents with a + * different amount of data. length will be ignored. + */ +#define FILE_XCHG_RANGE_TO_EOF (1 << 3) + +/* Flush all changes in file data and file metadata to disk before returning. */ +#define FILE_XCHG_RANGE_FSYNC (1 << 4) + +/* Dry run; do all the parameter verification but do not change anything. */ +#define FILE_XCHG_RANGE_DRY_RUN (1 << 5) + +/* + * Do not exchange any part of the range where file1's mapping is a hole. This + * can be used to emulate scatter-gather atomic writes with a temp file. + */ +#define FILE_XCHG_RANGE_SKIP_FILE1_HOLES (1 << 6) + +/* + * Commit the contents of file1 into file2 if file2 has the same inode number, + * mtime, and ctime as the arguments provided to the call. The old contents of + * file2 will be moved to file1. + * + * With this flag, all committed information can be retrieved even if the + * system crashes or is rebooted. This includes writing through or flushing a + * disk cache if present. The call blocks until the device reports that the + * commit is complete. + * + * This flag should not be combined with NONATOMIC. It can be combined with + * SKIP_FILE1_HOLES. + */ +#define FILE_XCHG_RANGE_COMMIT (FILE_XCHG_RANGE_FILE2_FRESH | \ + FILE_XCHG_RANGE_FSYNC) + +#define FILE_XCHG_RANGE_ALL_FLAGS (FILE_XCHG_RANGE_NONATOMIC | \ + FILE_XCHG_RANGE_FILE2_FRESH | \ + FILE_XCHG_RANGE_FULL_FILES | \ + FILE_XCHG_RANGE_TO_EOF | \ + FILE_XCHG_RANGE_FSYNC | \ + FILE_XCHG_RANGE_DRY_RUN | \ + FILE_XCHG_RANGE_SKIP_FILE1_HOLES) + +#define FIEXCHANGE_RANGE _IOWR('X', 129, struct file_xchg_range) + +#endif /* _LINUX_FIEXCHANGE_H */ diff --git a/src/global.h b/src/global.h index b44070993c..49570ef117 100644 --- a/src/global.h +++ b/src/global.h @@ -171,6 +171,12 @@ #include #endif +#ifdef HAVE_FIEXCHANGE +# include +#else +# include "fiexchange.h" +#endif + static inline unsigned long long rounddown_64(unsigned long long x, unsigned int y) { From patchwork Wed Mar 1 02:59:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Darrick J. Wong" X-Patchwork-Id: 13155532 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DF3D2C6FA8E for ; Wed, 1 Mar 2023 02:59:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229600AbjCAC7r (ORCPT ); Tue, 28 Feb 2023 21:59:47 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:40338 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229756AbjCAC7q (ORCPT ); Tue, 28 Feb 2023 21:59:46 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1B4AC7692; Tue, 28 Feb 2023 18:59:45 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id A2C0E6122C; Wed, 1 Mar 2023 02:59:44 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 09F6DC4339C; Wed, 1 Mar 2023 02:59:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1677639584; bh=cWszxIJmhZ2jvP2wtTOB3XoOKrpxJBKvEuJtMu6hraA=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=RWrzF/7MQfngivs/CEX5mZAzBehFvEgb1j12Hxgcp3werZjM+Tux2AzR2bhbtyLp4 0zwXeVvLiTSWZ7qzhJe9hJOHJOQIXHuquawTIDiVGbDSSJ/daTyoNYRfKp/fCor0Ii OzU97Ahs8vTTrDCHtdk/kIAxl1cdDpBjVfrlLdOOCEih8VdjhWeubLpxqlG8VDP+K3 snvbA6ZmPSfO2LUOnyGx8evqREYrGAa3zqqgSA9YdY5BXsGQbceOdtQF+FKTY3qDv0 xyL5HSK5YYoi1eUQti4n31dNPXm708WHun7m291XIIcwpxbsQL7RscdQXb2lkDJQ5W 5WomtLHPF7Pfw== Subject: [PATCH 7/7] fsstress: update for FIEXCHANGE_RANGE From: "Darrick J. Wong" To: djwong@kernel.org, zlang@redhat.com Cc: linux-xfs@vger.kernel.org, fstests@vger.kernel.org, guan@eryu.me Date: Tue, 28 Feb 2023 18:59:43 -0800 Message-ID: <167763958362.3796922.2350291536547146358.stgit@magnolia> In-Reply-To: <167763954409.3796922.11086772690906428270.stgit@magnolia> References: <167763954409.3796922.11086772690906428270.stgit@magnolia> User-Agent: StGit/0.19 MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-xfs@vger.kernel.org From: Darrick J. Wong Teach this stress tool to be able to use the file content exchange ioctl. Signed-off-by: Darrick J. Wong --- ltp/fsstress.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/ltp/fsstress.c b/ltp/fsstress.c index 10608fb554..0fba3d92a0 100644 --- a/ltp/fsstress.c +++ b/ltp/fsstress.c @@ -143,6 +143,7 @@ typedef enum { OP_URING_WRITE, OP_WRITE, OP_WRITEV, + OP_XCHGRANGE, OP_LAST } opty_t; @@ -272,6 +273,8 @@ void uring_read_f(opnum_t, long); void uring_write_f(opnum_t, long); void write_f(opnum_t, long); void writev_f(opnum_t, long); +void xchgrange_f(opnum_t, long); + char *xattr_flag_to_string(int); struct opdesc ops[OP_LAST] = { @@ -340,6 +343,7 @@ struct opdesc ops[OP_LAST] = { [OP_URING_WRITE] = {"uring_write", uring_write_f, 1, 1 }, [OP_WRITE] = {"write", write_f, 4, 1 }, [OP_WRITEV] = {"writev", writev_f, 4, 1 }, + [OP_XCHGRANGE] = {"xchgrange", xchgrange_f, 4, 1 }, }, *ops_end; flist_t flist[FT_nft] = { @@ -2494,6 +2498,170 @@ chown_f(opnum_t opno, long r) free_pathname(&f); } +/* exchange some arbitrary range of f1 to f2...fn. */ +void +xchgrange_f( + opnum_t opno, + long r) +{ +#ifdef FIEXCHANGE_RANGE + struct file_xchg_range fxr = { 0 }; + static __u64 swap_flags = 0; + struct pathname fpath1; + struct pathname fpath2; + struct stat64 stat1; + struct stat64 stat2; + char inoinfo1[1024]; + char inoinfo2[1024]; + off64_t lr; + off64_t off1; + off64_t off2; + off64_t max_off2; + size_t len; + int v1; + int v2; + int fd1; + int fd2; + int ret; + int tries = 0; + int e; + + /* Load paths */ + init_pathname(&fpath1); + if (!get_fname(FT_REGm, r, &fpath1, NULL, NULL, &v1)) { + if (v1) + printf("%d/%lld: xchgrange read - no filename\n", + procid, opno); + goto out_fpath1; + } + + init_pathname(&fpath2); + if (!get_fname(FT_REGm, random(), &fpath2, NULL, NULL, &v2)) { + if (v2) + printf("%d/%lld: xchgrange write - no filename\n", + procid, opno); + goto out_fpath2; + } + + /* Open files */ + fd1 = open_path(&fpath1, O_RDONLY); + e = fd1 < 0 ? errno : 0; + check_cwd(); + if (fd1 < 0) { + if (v1) + printf("%d/%lld: xchgrange read - open %s failed %d\n", + procid, opno, fpath1.path, e); + goto out_fpath2; + } + + fd2 = open_path(&fpath2, O_WRONLY); + e = fd2 < 0 ? errno : 0; + check_cwd(); + if (fd2 < 0) { + if (v2) + printf("%d/%lld: xchgrange write - open %s failed %d\n", + procid, opno, fpath2.path, e); + goto out_fd1; + } + + /* Get file stats */ + if (fstat64(fd1, &stat1) < 0) { + if (v1) + printf("%d/%lld: xchgrange read - fstat64 %s failed %d\n", + procid, opno, fpath1.path, errno); + goto out_fd2; + } + inode_info(inoinfo1, sizeof(inoinfo1), &stat1, v1); + + if (fstat64(fd2, &stat2) < 0) { + if (v2) + printf("%d/%lld: xchgrange write - fstat64 %s failed %d\n", + procid, opno, fpath2.path, errno); + goto out_fd2; + } + inode_info(inoinfo2, sizeof(inoinfo2), &stat2, v2); + + if (stat1.st_size < (stat1.st_blksize * 2) || + stat2.st_size < (stat2.st_blksize * 2)) { + if (v2) + printf("%d/%lld: xchgrange - files are too small\n", + procid, opno); + goto out_fd2; + } + + /* Never let us swap more than 1/4 of the files. */ + len = (random() % FILELEN_MAX) + 1; + if (len > stat1.st_size / 4) + len = stat1.st_size / 4; + if (len > stat2.st_size / 4) + len = stat2.st_size / 4; + len = rounddown_64(len, stat1.st_blksize); + if (len == 0) + len = stat1.st_blksize; + + /* Calculate offsets */ + lr = ((int64_t)random() << 32) + random(); + if (stat1.st_size == len) + off1 = 0; + else + off1 = (off64_t)(lr % MIN(stat1.st_size - len, MAXFSIZE)); + off1 %= maxfsize; + off1 = rounddown_64(off1, stat1.st_blksize); + + /* + * If srcfile == destfile, randomly generate destination ranges + * until we find one that doesn't overlap the source range. + */ + max_off2 = MIN(stat2.st_size - len, MAXFSIZE); + do { + lr = ((int64_t)random() << 32) + random(); + if (stat2.st_size == len) + off2 = 0; + else + off2 = (off64_t)(lr % max_off2); + off2 %= maxfsize; + off2 = rounddown_64(off2, stat2.st_blksize); + } while (stat1.st_ino == stat2.st_ino && + llabs(off2 - off1) < len && + tries++ < 10); + + /* Swap data blocks */ + fxr.file1_fd = fd1; + fxr.file1_offset = off1; + fxr.length = len; + fxr.file2_offset = off2; + fxr.flags = swap_flags; + +retry: + ret = ioctl(fd2, FIEXCHANGE_RANGE, &fxr); + e = ret < 0 ? errno : 0; + if (e == EOPNOTSUPP && !(swap_flags & FILE_XCHG_RANGE_NONATOMIC)) { + swap_flags = FILE_XCHG_RANGE_NONATOMIC; + fxr.flags |= swap_flags; + goto retry; + } + if (v1 || v2) { + printf("%d/%lld: xchgrange %s%s [%lld,%lld] -> %s%s [%lld,%lld]", + procid, opno, + fpath1.path, inoinfo1, (long long)off1, (long long)len, + fpath2.path, inoinfo2, (long long)off2, (long long)len); + + if (ret < 0) + printf(" error %d", e); + printf("\n"); + } + +out_fd2: + close(fd2); +out_fd1: + close(fd1); +out_fpath2: + free_pathname(&fpath2); +out_fpath1: + free_pathname(&fpath1); +#endif +} + /* reflink some arbitrary range of f1 to f2. */ void clonerange_f(