diff mbox series

[1/1] xfs: test filesystem recovery with rdump

Message ID 174259233533.743419.11473495762149004746.stgit@frogsfrogsfrogs (mailing list archive)
State New
Headers show
Series [1/1] xfs: test filesystem recovery with rdump | expand

Commit Message

Darrick J. Wong March 21, 2025, 9:27 p.m. UTC
From: Darrick J. Wong <djwong@kernel.org>

Test how well we can dump a fully populated filesystem's contents.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
 tests/xfs/1895     |  153 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/xfs/1895.out |    6 ++
 2 files changed, 159 insertions(+)
 create mode 100755 tests/xfs/1895
 create mode 100644 tests/xfs/1895.out

Comments

Zorro Lang March 22, 2025, 8:04 p.m. UTC | #1
On Fri, Mar 21, 2025 at 02:27:07PM -0700, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@kernel.org>
> 
> Test how well we can dump a fully populated filesystem's contents.
> 
> Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
> Reviewed-by: Christoph Hellwig <hch@lst.de>
> ---
>  tests/xfs/1895     |  153 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  tests/xfs/1895.out |    6 ++
>  2 files changed, 159 insertions(+)
>  create mode 100755 tests/xfs/1895
>  create mode 100644 tests/xfs/1895.out
> 
> 
> diff --git a/tests/xfs/1895 b/tests/xfs/1895
> new file mode 100755
> index 00000000000000..18b534d328e9fd
> --- /dev/null
> +++ b/tests/xfs/1895
> @@ -0,0 +1,153 @@
> +#! /bin/bash
> +# SPDX-License-Identifier: GPL-2.0
> +# Copyright (c) 2025 Oracle, Inc.  All Rights Reserved.
> +#
> +# FS QA Test No. 1895
> +#
> +# Populate a XFS filesystem, ensure that rdump can "recover" the contents to
> +# another directory, and compare the contents.
> +#
> +. ./common/preamble
> +_begin_fstest auto scrub
> +
> +_cleanup()
> +{
> +	command -v _kill_fsstress &>/dev/null && _kill_fsstress

I'm wondering why you always do "command -v _kill_fsstress &>/dev/null" before
_kill_fsstress, isn't _kill_fsstress a common helper in common/rc ?

Thanks,
Zorro

> +	cd /
> +	test -e "$testfiles" && rm -r -f $testfiles
> +}
> +
> +_register_cleanup "_cleanup" BUS
> +
> +# Import common functions.
> +. ./common/filter
> +. ./common/populate
> +. ./common/fuzzy
> +
> +_require_xfs_db_command "rdump"
> +_require_test
> +_require_scratch
> +_require_scrub
> +_require_populate_commands
> +
> +make_md5()
> +{
> +	(cd $1 ; find . -type f -print0 | xargs -0 md5sum) > $tmp.md5.$2
> +}
> +
> +cmp_md5()
> +{
> +	(cd $1 ; md5sum --quiet -c $tmp.md5.$2)
> +}
> +
> +make_stat()
> +{
> +	# columns:	raw mode in hex,
> +	# 		major rdev for special
> +	# 		minor rdev for special
> +	# 		uid of owner
> +	# 		gid of owner
> +	# 		file type
> +	# 		total size
> +	# 		mtime
> +	# 		name
> +	# We can't directly control directory sizes so filter them.
> +	# Too many things can bump (or not) atime so don't test that.
> +	(cd $1 ; find . -print0 |
> +		xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n' |
> +		sed -e 's/ directory [1-9][0-9]* / directory SIZE /g' |
> +		sort) > $tmp.stat.$2
> +}
> +
> +cmp_stat()
> +{
> +	diff -u $tmp.stat.$1 $tmp.stat.$2
> +}
> +
> +make_stat_files() {
> +	for file in "${FILES[@]}"; do
> +		find "$1/$file" -print0 | xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n'
> +	done | sed \
> +		-e 's/ directory [1-9][0-9]* / directory SIZE /g' \
> +		-e "s| $1| DUMPDIR|g" \
> +		| sort > $tmp.stat.files.$2
> +}
> +
> +cmp_stat_files()
> +{
> +	diff -u $tmp.stat.files.$1 $tmp.stat.files.$2
> +}
> +
> +make_stat_dir() {
> +	find "$1" -print0 | \
> +		xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n' | sed \
> +		-e 's/ directory [1-9][0-9]* / directory SIZE /g' \
> +		-e "s| $1| DUMPDIR|g" \
> +		| sort > $tmp.stat.dir.$2
> +}
> +
> +cmp_stat_dir()
> +{
> +	diff -u $tmp.stat.dir.$1 $tmp.stat.dir.$2
> +}
> +
> +FILES=(
> +	"/S_IFDIR.FMT_INLINE"
> +	"/S_IFBLK"
> +	"/S_IFCHR"
> +	"/S_IFLNK.FMT_LOCAL"
> +	"/S_IFIFO"
> +	"/S_IFDIR.FMT_INLINE/00000001"
> +	"/ATTR.FMT_EXTENTS_REMOTE3K"
> +	"/S_IFREG.FMT_EXTENTS"
> +	"/S_IFREG.FMT_BTREE"
> +	"/BNOBT"
> +	"/S_IFDIR.FMT_BLOCK"
> +)
> +DIR="/S_IFDIR.FMT_LEAF"
> +
> +testfiles=$TEST_DIR/$seq
> +mkdir -p $testfiles
> +
> +echo "Format and populate"
> +_scratch_populate_cached nofill > $seqres.full 2>&1
> +_scratch_mount
> +
> +_run_fsstress -n 500 -d $SCRATCH_MNT/newfiles
> +
> +make_stat $SCRATCH_MNT before
> +make_md5 $SCRATCH_MNT before
> +make_stat_files $SCRATCH_MNT before
> +make_stat_dir $SCRATCH_MNT/$DIR before
> +_scratch_unmount
> +
> +echo "Recover filesystem"
> +dumpdir1=$testfiles/rdump
> +dumpdir2=$testfiles/sdump
> +dumpdir3=$testfiles/tdump
> +rm -r -f $dumpdir1 $dumpdir2 $dumpdir3
> +
> +# as of linux 6.12 fchownat does not work on symlinks
> +_scratch_xfs_db -c "rdump / $dumpdir1" | sed -e '/could not be set/d'
> +_scratch_xfs_db -c "rdump ${FILES[*]} $dumpdir2" | sed -e '/could not be set/d'
> +_scratch_xfs_db -c "rdump $DIR $dumpdir3" | sed -e '/could not be set/d'
> +
> +echo "Check file contents"
> +make_stat $dumpdir1 after
> +cmp_stat before after
> +cmp_md5 $dumpdir1 before
> +
> +echo "Check selected files contents"
> +make_stat_files $dumpdir2 after
> +cmp_stat_files before after
> +
> +echo "Check single dir extraction contents"
> +make_stat_dir $dumpdir3 after
> +cmp_stat_dir before after
> +
> +# remount so we can check this fs
> +_scratch_mount
> +
> +# success, all done
> +status=0
> +exit
> diff --git a/tests/xfs/1895.out b/tests/xfs/1895.out
> new file mode 100644
> index 00000000000000..de639ed3fc7e38
> --- /dev/null
> +++ b/tests/xfs/1895.out
> @@ -0,0 +1,6 @@
> +QA output created by 1895
> +Format and populate
> +Recover filesystem
> +Check file contents
> +Check selected files contents
> +Check single dir extraction contents
>
Darrick J. Wong March 25, 2025, 12:50 a.m. UTC | #2
On Sun, Mar 23, 2025 at 04:04:29AM +0800, Zorro Lang wrote:
> On Fri, Mar 21, 2025 at 02:27:07PM -0700, Darrick J. Wong wrote:
> > From: Darrick J. Wong <djwong@kernel.org>
> > 
> > Test how well we can dump a fully populated filesystem's contents.
> > 
> > Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
> > Reviewed-by: Christoph Hellwig <hch@lst.de>
> > ---
> >  tests/xfs/1895     |  153 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  tests/xfs/1895.out |    6 ++
> >  2 files changed, 159 insertions(+)
> >  create mode 100755 tests/xfs/1895
> >  create mode 100644 tests/xfs/1895.out
> > 
> > 
> > diff --git a/tests/xfs/1895 b/tests/xfs/1895
> > new file mode 100755
> > index 00000000000000..18b534d328e9fd
> > --- /dev/null
> > +++ b/tests/xfs/1895
> > @@ -0,0 +1,153 @@
> > +#! /bin/bash
> > +# SPDX-License-Identifier: GPL-2.0
> > +# Copyright (c) 2025 Oracle, Inc.  All Rights Reserved.
> > +#
> > +# FS QA Test No. 1895
> > +#
> > +# Populate a XFS filesystem, ensure that rdump can "recover" the contents to
> > +# another directory, and compare the contents.
> > +#
> > +. ./common/preamble
> > +_begin_fstest auto scrub
> > +
> > +_cleanup()
> > +{
> > +	command -v _kill_fsstress &>/dev/null && _kill_fsstress
> 
> I'm wondering why you always do "command -v _kill_fsstress &>/dev/null" before
> _kill_fsstress, isn't _kill_fsstress a common helper in common/rc ?

Yeah, I probably copy-pasta'd that from common/preamble.  Will remove it
before the next posting, assuming you don't decide to fix+merge it.

--D

> Thanks,
> Zorro
> 
> > +	cd /
> > +	test -e "$testfiles" && rm -r -f $testfiles
> > +}
> > +
> > +_register_cleanup "_cleanup" BUS
> > +
> > +# Import common functions.
> > +. ./common/filter
> > +. ./common/populate
> > +. ./common/fuzzy
> > +
> > +_require_xfs_db_command "rdump"
> > +_require_test
> > +_require_scratch
> > +_require_scrub
> > +_require_populate_commands
> > +
> > +make_md5()
> > +{
> > +	(cd $1 ; find . -type f -print0 | xargs -0 md5sum) > $tmp.md5.$2
> > +}
> > +
> > +cmp_md5()
> > +{
> > +	(cd $1 ; md5sum --quiet -c $tmp.md5.$2)
> > +}
> > +
> > +make_stat()
> > +{
> > +	# columns:	raw mode in hex,
> > +	# 		major rdev for special
> > +	# 		minor rdev for special
> > +	# 		uid of owner
> > +	# 		gid of owner
> > +	# 		file type
> > +	# 		total size
> > +	# 		mtime
> > +	# 		name
> > +	# We can't directly control directory sizes so filter them.
> > +	# Too many things can bump (or not) atime so don't test that.
> > +	(cd $1 ; find . -print0 |
> > +		xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n' |
> > +		sed -e 's/ directory [1-9][0-9]* / directory SIZE /g' |
> > +		sort) > $tmp.stat.$2
> > +}
> > +
> > +cmp_stat()
> > +{
> > +	diff -u $tmp.stat.$1 $tmp.stat.$2
> > +}
> > +
> > +make_stat_files() {
> > +	for file in "${FILES[@]}"; do
> > +		find "$1/$file" -print0 | xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n'
> > +	done | sed \
> > +		-e 's/ directory [1-9][0-9]* / directory SIZE /g' \
> > +		-e "s| $1| DUMPDIR|g" \
> > +		| sort > $tmp.stat.files.$2
> > +}
> > +
> > +cmp_stat_files()
> > +{
> > +	diff -u $tmp.stat.files.$1 $tmp.stat.files.$2
> > +}
> > +
> > +make_stat_dir() {
> > +	find "$1" -print0 | \
> > +		xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n' | sed \
> > +		-e 's/ directory [1-9][0-9]* / directory SIZE /g' \
> > +		-e "s| $1| DUMPDIR|g" \
> > +		| sort > $tmp.stat.dir.$2
> > +}
> > +
> > +cmp_stat_dir()
> > +{
> > +	diff -u $tmp.stat.dir.$1 $tmp.stat.dir.$2
> > +}
> > +
> > +FILES=(
> > +	"/S_IFDIR.FMT_INLINE"
> > +	"/S_IFBLK"
> > +	"/S_IFCHR"
> > +	"/S_IFLNK.FMT_LOCAL"
> > +	"/S_IFIFO"
> > +	"/S_IFDIR.FMT_INLINE/00000001"
> > +	"/ATTR.FMT_EXTENTS_REMOTE3K"
> > +	"/S_IFREG.FMT_EXTENTS"
> > +	"/S_IFREG.FMT_BTREE"
> > +	"/BNOBT"
> > +	"/S_IFDIR.FMT_BLOCK"
> > +)
> > +DIR="/S_IFDIR.FMT_LEAF"
> > +
> > +testfiles=$TEST_DIR/$seq
> > +mkdir -p $testfiles
> > +
> > +echo "Format and populate"
> > +_scratch_populate_cached nofill > $seqres.full 2>&1
> > +_scratch_mount
> > +
> > +_run_fsstress -n 500 -d $SCRATCH_MNT/newfiles
> > +
> > +make_stat $SCRATCH_MNT before
> > +make_md5 $SCRATCH_MNT before
> > +make_stat_files $SCRATCH_MNT before
> > +make_stat_dir $SCRATCH_MNT/$DIR before
> > +_scratch_unmount
> > +
> > +echo "Recover filesystem"
> > +dumpdir1=$testfiles/rdump
> > +dumpdir2=$testfiles/sdump
> > +dumpdir3=$testfiles/tdump
> > +rm -r -f $dumpdir1 $dumpdir2 $dumpdir3
> > +
> > +# as of linux 6.12 fchownat does not work on symlinks
> > +_scratch_xfs_db -c "rdump / $dumpdir1" | sed -e '/could not be set/d'
> > +_scratch_xfs_db -c "rdump ${FILES[*]} $dumpdir2" | sed -e '/could not be set/d'
> > +_scratch_xfs_db -c "rdump $DIR $dumpdir3" | sed -e '/could not be set/d'
> > +
> > +echo "Check file contents"
> > +make_stat $dumpdir1 after
> > +cmp_stat before after
> > +cmp_md5 $dumpdir1 before
> > +
> > +echo "Check selected files contents"
> > +make_stat_files $dumpdir2 after
> > +cmp_stat_files before after
> > +
> > +echo "Check single dir extraction contents"
> > +make_stat_dir $dumpdir3 after
> > +cmp_stat_dir before after
> > +
> > +# remount so we can check this fs
> > +_scratch_mount
> > +
> > +# success, all done
> > +status=0
> > +exit
> > diff --git a/tests/xfs/1895.out b/tests/xfs/1895.out
> > new file mode 100644
> > index 00000000000000..de639ed3fc7e38
> > --- /dev/null
> > +++ b/tests/xfs/1895.out
> > @@ -0,0 +1,6 @@
> > +QA output created by 1895
> > +Format and populate
> > +Recover filesystem
> > +Check file contents
> > +Check selected files contents
> > +Check single dir extraction contents
> > 
> 
>
Zorro Lang March 25, 2025, 1:08 a.m. UTC | #3
On Mon, Mar 24, 2025 at 05:50:26PM -0700, Darrick J. Wong wrote:
> On Sun, Mar 23, 2025 at 04:04:29AM +0800, Zorro Lang wrote:
> > On Fri, Mar 21, 2025 at 02:27:07PM -0700, Darrick J. Wong wrote:
> > > From: Darrick J. Wong <djwong@kernel.org>
> > > 
> > > Test how well we can dump a fully populated filesystem's contents.
> > > 
> > > Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
> > > Reviewed-by: Christoph Hellwig <hch@lst.de>
> > > ---
> > >  tests/xfs/1895     |  153 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> > >  tests/xfs/1895.out |    6 ++
> > >  2 files changed, 159 insertions(+)
> > >  create mode 100755 tests/xfs/1895
> > >  create mode 100644 tests/xfs/1895.out
> > > 
> > > 
> > > diff --git a/tests/xfs/1895 b/tests/xfs/1895
> > > new file mode 100755
> > > index 00000000000000..18b534d328e9fd
> > > --- /dev/null
> > > +++ b/tests/xfs/1895
> > > @@ -0,0 +1,153 @@
> > > +#! /bin/bash
> > > +# SPDX-License-Identifier: GPL-2.0
> > > +# Copyright (c) 2025 Oracle, Inc.  All Rights Reserved.
> > > +#
> > > +# FS QA Test No. 1895
> > > +#
> > > +# Populate a XFS filesystem, ensure that rdump can "recover" the contents to
> > > +# another directory, and compare the contents.
> > > +#
> > > +. ./common/preamble
> > > +_begin_fstest auto scrub
> > > +
> > > +_cleanup()
> > > +{
> > > +	command -v _kill_fsstress &>/dev/null && _kill_fsstress
> > 
> > I'm wondering why you always do "command -v _kill_fsstress &>/dev/null" before
> > _kill_fsstress, isn't _kill_fsstress a common helper in common/rc ?
> 
> Yeah, I probably copy-pasta'd that from common/preamble.  Will remove it
> before the next posting, assuming you don't decide to fix+merge it.

I can "fix+merge" that:) if you don't have more changes, except:

  - command -v _kill_fsstress &>/dev/null && _kill_fsstress
  + _kill_fsstress

Thanks,
Zorro

> 
> --D
> 
> > Thanks,
> > Zorro
> > 
> > > +	cd /
> > > +	test -e "$testfiles" && rm -r -f $testfiles
> > > +}
> > > +
> > > +_register_cleanup "_cleanup" BUS
> > > +
> > > +# Import common functions.
> > > +. ./common/filter
> > > +. ./common/populate
> > > +. ./common/fuzzy
> > > +
> > > +_require_xfs_db_command "rdump"
> > > +_require_test
> > > +_require_scratch
> > > +_require_scrub
> > > +_require_populate_commands
> > > +
> > > +make_md5()
> > > +{
> > > +	(cd $1 ; find . -type f -print0 | xargs -0 md5sum) > $tmp.md5.$2
> > > +}
> > > +
> > > +cmp_md5()
> > > +{
> > > +	(cd $1 ; md5sum --quiet -c $tmp.md5.$2)
> > > +}
> > > +
> > > +make_stat()
> > > +{
> > > +	# columns:	raw mode in hex,
> > > +	# 		major rdev for special
> > > +	# 		minor rdev for special
> > > +	# 		uid of owner
> > > +	# 		gid of owner
> > > +	# 		file type
> > > +	# 		total size
> > > +	# 		mtime
> > > +	# 		name
> > > +	# We can't directly control directory sizes so filter them.
> > > +	# Too many things can bump (or not) atime so don't test that.
> > > +	(cd $1 ; find . -print0 |
> > > +		xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n' |
> > > +		sed -e 's/ directory [1-9][0-9]* / directory SIZE /g' |
> > > +		sort) > $tmp.stat.$2
> > > +}
> > > +
> > > +cmp_stat()
> > > +{
> > > +	diff -u $tmp.stat.$1 $tmp.stat.$2
> > > +}
> > > +
> > > +make_stat_files() {
> > > +	for file in "${FILES[@]}"; do
> > > +		find "$1/$file" -print0 | xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n'
> > > +	done | sed \
> > > +		-e 's/ directory [1-9][0-9]* / directory SIZE /g' \
> > > +		-e "s| $1| DUMPDIR|g" \
> > > +		| sort > $tmp.stat.files.$2
> > > +}
> > > +
> > > +cmp_stat_files()
> > > +{
> > > +	diff -u $tmp.stat.files.$1 $tmp.stat.files.$2
> > > +}
> > > +
> > > +make_stat_dir() {
> > > +	find "$1" -print0 | \
> > > +		xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n' | sed \
> > > +		-e 's/ directory [1-9][0-9]* / directory SIZE /g' \
> > > +		-e "s| $1| DUMPDIR|g" \
> > > +		| sort > $tmp.stat.dir.$2
> > > +}
> > > +
> > > +cmp_stat_dir()
> > > +{
> > > +	diff -u $tmp.stat.dir.$1 $tmp.stat.dir.$2
> > > +}
> > > +
> > > +FILES=(
> > > +	"/S_IFDIR.FMT_INLINE"
> > > +	"/S_IFBLK"
> > > +	"/S_IFCHR"
> > > +	"/S_IFLNK.FMT_LOCAL"
> > > +	"/S_IFIFO"
> > > +	"/S_IFDIR.FMT_INLINE/00000001"
> > > +	"/ATTR.FMT_EXTENTS_REMOTE3K"
> > > +	"/S_IFREG.FMT_EXTENTS"
> > > +	"/S_IFREG.FMT_BTREE"
> > > +	"/BNOBT"
> > > +	"/S_IFDIR.FMT_BLOCK"
> > > +)
> > > +DIR="/S_IFDIR.FMT_LEAF"
> > > +
> > > +testfiles=$TEST_DIR/$seq
> > > +mkdir -p $testfiles
> > > +
> > > +echo "Format and populate"
> > > +_scratch_populate_cached nofill > $seqres.full 2>&1
> > > +_scratch_mount
> > > +
> > > +_run_fsstress -n 500 -d $SCRATCH_MNT/newfiles
> > > +
> > > +make_stat $SCRATCH_MNT before
> > > +make_md5 $SCRATCH_MNT before
> > > +make_stat_files $SCRATCH_MNT before
> > > +make_stat_dir $SCRATCH_MNT/$DIR before
> > > +_scratch_unmount
> > > +
> > > +echo "Recover filesystem"
> > > +dumpdir1=$testfiles/rdump
> > > +dumpdir2=$testfiles/sdump
> > > +dumpdir3=$testfiles/tdump
> > > +rm -r -f $dumpdir1 $dumpdir2 $dumpdir3
> > > +
> > > +# as of linux 6.12 fchownat does not work on symlinks
> > > +_scratch_xfs_db -c "rdump / $dumpdir1" | sed -e '/could not be set/d'
> > > +_scratch_xfs_db -c "rdump ${FILES[*]} $dumpdir2" | sed -e '/could not be set/d'
> > > +_scratch_xfs_db -c "rdump $DIR $dumpdir3" | sed -e '/could not be set/d'
> > > +
> > > +echo "Check file contents"
> > > +make_stat $dumpdir1 after
> > > +cmp_stat before after
> > > +cmp_md5 $dumpdir1 before
> > > +
> > > +echo "Check selected files contents"
> > > +make_stat_files $dumpdir2 after
> > > +cmp_stat_files before after
> > > +
> > > +echo "Check single dir extraction contents"
> > > +make_stat_dir $dumpdir3 after
> > > +cmp_stat_dir before after
> > > +
> > > +# remount so we can check this fs
> > > +_scratch_mount
> > > +
> > > +# success, all done
> > > +status=0
> > > +exit
> > > diff --git a/tests/xfs/1895.out b/tests/xfs/1895.out
> > > new file mode 100644
> > > index 00000000000000..de639ed3fc7e38
> > > --- /dev/null
> > > +++ b/tests/xfs/1895.out
> > > @@ -0,0 +1,6 @@
> > > +QA output created by 1895
> > > +Format and populate
> > > +Recover filesystem
> > > +Check file contents
> > > +Check selected files contents
> > > +Check single dir extraction contents
> > > 
> > 
> > 
>
Darrick J. Wong March 25, 2025, 1:20 a.m. UTC | #4
On Tue, Mar 25, 2025 at 09:08:51AM +0800, Zorro Lang wrote:
> On Mon, Mar 24, 2025 at 05:50:26PM -0700, Darrick J. Wong wrote:
> > On Sun, Mar 23, 2025 at 04:04:29AM +0800, Zorro Lang wrote:
> > > On Fri, Mar 21, 2025 at 02:27:07PM -0700, Darrick J. Wong wrote:
> > > > From: Darrick J. Wong <djwong@kernel.org>
> > > > 
> > > > Test how well we can dump a fully populated filesystem's contents.
> > > > 
> > > > Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
> > > > Reviewed-by: Christoph Hellwig <hch@lst.de>
> > > > ---
> > > >  tests/xfs/1895     |  153 ++++++++++++++++++++++++++++++++++++++++++++++++++++
> > > >  tests/xfs/1895.out |    6 ++
> > > >  2 files changed, 159 insertions(+)
> > > >  create mode 100755 tests/xfs/1895
> > > >  create mode 100644 tests/xfs/1895.out
> > > > 
> > > > 
> > > > diff --git a/tests/xfs/1895 b/tests/xfs/1895
> > > > new file mode 100755
> > > > index 00000000000000..18b534d328e9fd
> > > > --- /dev/null
> > > > +++ b/tests/xfs/1895
> > > > @@ -0,0 +1,153 @@
> > > > +#! /bin/bash
> > > > +# SPDX-License-Identifier: GPL-2.0
> > > > +# Copyright (c) 2025 Oracle, Inc.  All Rights Reserved.
> > > > +#
> > > > +# FS QA Test No. 1895
> > > > +#
> > > > +# Populate a XFS filesystem, ensure that rdump can "recover" the contents to
> > > > +# another directory, and compare the contents.
> > > > +#
> > > > +. ./common/preamble
> > > > +_begin_fstest auto scrub
> > > > +
> > > > +_cleanup()
> > > > +{
> > > > +	command -v _kill_fsstress &>/dev/null && _kill_fsstress
> > > 
> > > I'm wondering why you always do "command -v _kill_fsstress &>/dev/null" before
> > > _kill_fsstress, isn't _kill_fsstress a common helper in common/rc ?
> > 
> > Yeah, I probably copy-pasta'd that from common/preamble.  Will remove it
> > before the next posting, assuming you don't decide to fix+merge it.
> 
> I can "fix+merge" that:) if you don't have more changes, except:
> 
>   - command -v _kill_fsstress &>/dev/null && _kill_fsstress
>   + _kill_fsstress

No changes other than applying hch's rvb that he attached to the other
thread.

--D

> Thanks,
> Zorro
> 
> > 
> > --D
> > 
> > > Thanks,
> > > Zorro
> > > 
> > > > +	cd /
> > > > +	test -e "$testfiles" && rm -r -f $testfiles
> > > > +}
> > > > +
> > > > +_register_cleanup "_cleanup" BUS
> > > > +
> > > > +# Import common functions.
> > > > +. ./common/filter
> > > > +. ./common/populate
> > > > +. ./common/fuzzy
> > > > +
> > > > +_require_xfs_db_command "rdump"
> > > > +_require_test
> > > > +_require_scratch
> > > > +_require_scrub
> > > > +_require_populate_commands
> > > > +
> > > > +make_md5()
> > > > +{
> > > > +	(cd $1 ; find . -type f -print0 | xargs -0 md5sum) > $tmp.md5.$2
> > > > +}
> > > > +
> > > > +cmp_md5()
> > > > +{
> > > > +	(cd $1 ; md5sum --quiet -c $tmp.md5.$2)
> > > > +}
> > > > +
> > > > +make_stat()
> > > > +{
> > > > +	# columns:	raw mode in hex,
> > > > +	# 		major rdev for special
> > > > +	# 		minor rdev for special
> > > > +	# 		uid of owner
> > > > +	# 		gid of owner
> > > > +	# 		file type
> > > > +	# 		total size
> > > > +	# 		mtime
> > > > +	# 		name
> > > > +	# We can't directly control directory sizes so filter them.
> > > > +	# Too many things can bump (or not) atime so don't test that.
> > > > +	(cd $1 ; find . -print0 |
> > > > +		xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n' |
> > > > +		sed -e 's/ directory [1-9][0-9]* / directory SIZE /g' |
> > > > +		sort) > $tmp.stat.$2
> > > > +}
> > > > +
> > > > +cmp_stat()
> > > > +{
> > > > +	diff -u $tmp.stat.$1 $tmp.stat.$2
> > > > +}
> > > > +
> > > > +make_stat_files() {
> > > > +	for file in "${FILES[@]}"; do
> > > > +		find "$1/$file" -print0 | xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n'
> > > > +	done | sed \
> > > > +		-e 's/ directory [1-9][0-9]* / directory SIZE /g' \
> > > > +		-e "s| $1| DUMPDIR|g" \
> > > > +		| sort > $tmp.stat.files.$2
> > > > +}
> > > > +
> > > > +cmp_stat_files()
> > > > +{
> > > > +	diff -u $tmp.stat.files.$1 $tmp.stat.files.$2
> > > > +}
> > > > +
> > > > +make_stat_dir() {
> > > > +	find "$1" -print0 | \
> > > > +		xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n' | sed \
> > > > +		-e 's/ directory [1-9][0-9]* / directory SIZE /g' \
> > > > +		-e "s| $1| DUMPDIR|g" \
> > > > +		| sort > $tmp.stat.dir.$2
> > > > +}
> > > > +
> > > > +cmp_stat_dir()
> > > > +{
> > > > +	diff -u $tmp.stat.dir.$1 $tmp.stat.dir.$2
> > > > +}
> > > > +
> > > > +FILES=(
> > > > +	"/S_IFDIR.FMT_INLINE"
> > > > +	"/S_IFBLK"
> > > > +	"/S_IFCHR"
> > > > +	"/S_IFLNK.FMT_LOCAL"
> > > > +	"/S_IFIFO"
> > > > +	"/S_IFDIR.FMT_INLINE/00000001"
> > > > +	"/ATTR.FMT_EXTENTS_REMOTE3K"
> > > > +	"/S_IFREG.FMT_EXTENTS"
> > > > +	"/S_IFREG.FMT_BTREE"
> > > > +	"/BNOBT"
> > > > +	"/S_IFDIR.FMT_BLOCK"
> > > > +)
> > > > +DIR="/S_IFDIR.FMT_LEAF"
> > > > +
> > > > +testfiles=$TEST_DIR/$seq
> > > > +mkdir -p $testfiles
> > > > +
> > > > +echo "Format and populate"
> > > > +_scratch_populate_cached nofill > $seqres.full 2>&1
> > > > +_scratch_mount
> > > > +
> > > > +_run_fsstress -n 500 -d $SCRATCH_MNT/newfiles
> > > > +
> > > > +make_stat $SCRATCH_MNT before
> > > > +make_md5 $SCRATCH_MNT before
> > > > +make_stat_files $SCRATCH_MNT before
> > > > +make_stat_dir $SCRATCH_MNT/$DIR before
> > > > +_scratch_unmount
> > > > +
> > > > +echo "Recover filesystem"
> > > > +dumpdir1=$testfiles/rdump
> > > > +dumpdir2=$testfiles/sdump
> > > > +dumpdir3=$testfiles/tdump
> > > > +rm -r -f $dumpdir1 $dumpdir2 $dumpdir3
> > > > +
> > > > +# as of linux 6.12 fchownat does not work on symlinks
> > > > +_scratch_xfs_db -c "rdump / $dumpdir1" | sed -e '/could not be set/d'
> > > > +_scratch_xfs_db -c "rdump ${FILES[*]} $dumpdir2" | sed -e '/could not be set/d'
> > > > +_scratch_xfs_db -c "rdump $DIR $dumpdir3" | sed -e '/could not be set/d'
> > > > +
> > > > +echo "Check file contents"
> > > > +make_stat $dumpdir1 after
> > > > +cmp_stat before after
> > > > +cmp_md5 $dumpdir1 before
> > > > +
> > > > +echo "Check selected files contents"
> > > > +make_stat_files $dumpdir2 after
> > > > +cmp_stat_files before after
> > > > +
> > > > +echo "Check single dir extraction contents"
> > > > +make_stat_dir $dumpdir3 after
> > > > +cmp_stat_dir before after
> > > > +
> > > > +# remount so we can check this fs
> > > > +_scratch_mount
> > > > +
> > > > +# success, all done
> > > > +status=0
> > > > +exit
> > > > diff --git a/tests/xfs/1895.out b/tests/xfs/1895.out
> > > > new file mode 100644
> > > > index 00000000000000..de639ed3fc7e38
> > > > --- /dev/null
> > > > +++ b/tests/xfs/1895.out
> > > > @@ -0,0 +1,6 @@
> > > > +QA output created by 1895
> > > > +Format and populate
> > > > +Recover filesystem
> > > > +Check file contents
> > > > +Check selected files contents
> > > > +Check single dir extraction contents
> > > > 
> > > 
> > > 
> > 
>
diff mbox series

Patch

diff --git a/tests/xfs/1895 b/tests/xfs/1895
new file mode 100755
index 00000000000000..18b534d328e9fd
--- /dev/null
+++ b/tests/xfs/1895
@@ -0,0 +1,153 @@ 
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2025 Oracle, Inc.  All Rights Reserved.
+#
+# FS QA Test No. 1895
+#
+# Populate a XFS filesystem, ensure that rdump can "recover" the contents to
+# another directory, and compare the contents.
+#
+. ./common/preamble
+_begin_fstest auto scrub
+
+_cleanup()
+{
+	command -v _kill_fsstress &>/dev/null && _kill_fsstress
+	cd /
+	test -e "$testfiles" && rm -r -f $testfiles
+}
+
+_register_cleanup "_cleanup" BUS
+
+# Import common functions.
+. ./common/filter
+. ./common/populate
+. ./common/fuzzy
+
+_require_xfs_db_command "rdump"
+_require_test
+_require_scratch
+_require_scrub
+_require_populate_commands
+
+make_md5()
+{
+	(cd $1 ; find . -type f -print0 | xargs -0 md5sum) > $tmp.md5.$2
+}
+
+cmp_md5()
+{
+	(cd $1 ; md5sum --quiet -c $tmp.md5.$2)
+}
+
+make_stat()
+{
+	# columns:	raw mode in hex,
+	# 		major rdev for special
+	# 		minor rdev for special
+	# 		uid of owner
+	# 		gid of owner
+	# 		file type
+	# 		total size
+	# 		mtime
+	# 		name
+	# We can't directly control directory sizes so filter them.
+	# Too many things can bump (or not) atime so don't test that.
+	(cd $1 ; find . -print0 |
+		xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n' |
+		sed -e 's/ directory [1-9][0-9]* / directory SIZE /g' |
+		sort) > $tmp.stat.$2
+}
+
+cmp_stat()
+{
+	diff -u $tmp.stat.$1 $tmp.stat.$2
+}
+
+make_stat_files() {
+	for file in "${FILES[@]}"; do
+		find "$1/$file" -print0 | xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n'
+	done | sed \
+		-e 's/ directory [1-9][0-9]* / directory SIZE /g' \
+		-e "s| $1| DUMPDIR|g" \
+		| sort > $tmp.stat.files.$2
+}
+
+cmp_stat_files()
+{
+	diff -u $tmp.stat.files.$1 $tmp.stat.files.$2
+}
+
+make_stat_dir() {
+	find "$1" -print0 | \
+		xargs -0 stat -c '%f %t:%T %u %g %F %s %Y %n' | sed \
+		-e 's/ directory [1-9][0-9]* / directory SIZE /g' \
+		-e "s| $1| DUMPDIR|g" \
+		| sort > $tmp.stat.dir.$2
+}
+
+cmp_stat_dir()
+{
+	diff -u $tmp.stat.dir.$1 $tmp.stat.dir.$2
+}
+
+FILES=(
+	"/S_IFDIR.FMT_INLINE"
+	"/S_IFBLK"
+	"/S_IFCHR"
+	"/S_IFLNK.FMT_LOCAL"
+	"/S_IFIFO"
+	"/S_IFDIR.FMT_INLINE/00000001"
+	"/ATTR.FMT_EXTENTS_REMOTE3K"
+	"/S_IFREG.FMT_EXTENTS"
+	"/S_IFREG.FMT_BTREE"
+	"/BNOBT"
+	"/S_IFDIR.FMT_BLOCK"
+)
+DIR="/S_IFDIR.FMT_LEAF"
+
+testfiles=$TEST_DIR/$seq
+mkdir -p $testfiles
+
+echo "Format and populate"
+_scratch_populate_cached nofill > $seqres.full 2>&1
+_scratch_mount
+
+_run_fsstress -n 500 -d $SCRATCH_MNT/newfiles
+
+make_stat $SCRATCH_MNT before
+make_md5 $SCRATCH_MNT before
+make_stat_files $SCRATCH_MNT before
+make_stat_dir $SCRATCH_MNT/$DIR before
+_scratch_unmount
+
+echo "Recover filesystem"
+dumpdir1=$testfiles/rdump
+dumpdir2=$testfiles/sdump
+dumpdir3=$testfiles/tdump
+rm -r -f $dumpdir1 $dumpdir2 $dumpdir3
+
+# as of linux 6.12 fchownat does not work on symlinks
+_scratch_xfs_db -c "rdump / $dumpdir1" | sed -e '/could not be set/d'
+_scratch_xfs_db -c "rdump ${FILES[*]} $dumpdir2" | sed -e '/could not be set/d'
+_scratch_xfs_db -c "rdump $DIR $dumpdir3" | sed -e '/could not be set/d'
+
+echo "Check file contents"
+make_stat $dumpdir1 after
+cmp_stat before after
+cmp_md5 $dumpdir1 before
+
+echo "Check selected files contents"
+make_stat_files $dumpdir2 after
+cmp_stat_files before after
+
+echo "Check single dir extraction contents"
+make_stat_dir $dumpdir3 after
+cmp_stat_dir before after
+
+# remount so we can check this fs
+_scratch_mount
+
+# success, all done
+status=0
+exit
diff --git a/tests/xfs/1895.out b/tests/xfs/1895.out
new file mode 100644
index 00000000000000..de639ed3fc7e38
--- /dev/null
+++ b/tests/xfs/1895.out
@@ -0,0 +1,6 @@ 
+QA output created by 1895
+Format and populate
+Recover filesystem
+Check file contents
+Check selected files contents
+Check single dir extraction contents