diff mbox series

[1/3] Initial bcachefs support

Message ID 20210427164419.3729180-2-kent.overstreet@gmail.com (mailing list archive)
State New, archived
Headers show
Series bcachefs support | expand

Commit Message

Kent Overstreet April 27, 2021, 4:44 p.m. UTC
From: Kent Overstreet <kmo@daterainc.com>

Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
---
 common/attr        |  6 ++++++
 common/config      |  3 +++
 common/dmlogwrites |  7 +++++++
 common/quota       |  4 ++--
 common/rc          | 31 +++++++++++++++++++++++++++++++
 tests/generic/042  |  3 ++-
 tests/generic/425  |  3 +++
 tests/generic/441  |  2 +-
 tests/generic/482  | 27 ++++++++++++++++++++-------
 tests/generic/558  |  2 ++
 10 files changed, 77 insertions(+), 11 deletions(-)

Comments

Eryu Guan May 9, 2021, 2:36 p.m. UTC | #1
On Tue, Apr 27, 2021 at 12:44:17PM -0400, Kent Overstreet wrote:
> From: Kent Overstreet <kmo@daterainc.com>

Better to add commit logs at least to give an example about how to setup
fstests to test bcachefs.

> 
> Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
> ---
>  common/attr        |  6 ++++++
>  common/config      |  3 +++
>  common/dmlogwrites |  7 +++++++
>  common/quota       |  4 ++--
>  common/rc          | 31 +++++++++++++++++++++++++++++++
>  tests/generic/042  |  3 ++-
>  tests/generic/425  |  3 +++
>  tests/generic/441  |  2 +-
>  tests/generic/482  | 27 ++++++++++++++++++++-------
>  tests/generic/558  |  2 ++
>  10 files changed, 77 insertions(+), 11 deletions(-)
> 
> diff --git a/common/attr b/common/attr
> index 669909d600..42ceab9233 100644
> --- a/common/attr
> +++ b/common/attr
> @@ -33,6 +33,9 @@ _acl_get_max()
>  			echo 506
>  		fi
>  		;;
> +	bcachefs)
> +		echo 251
> +		;;
>  	*)
>  		echo 0
>  		;;
> @@ -273,6 +276,9 @@ pvfs2)
>  9p|ceph|nfs)
>  	MAX_ATTRVAL_SIZE=65536
>  	;;
> +bcachefs)
> +	MAX_ATTRVAL_SIZE=1024
> +	;;
>  *)
>  	# Assume max ~1 block of attrs
>  	BLOCK_SIZE=`_get_block_size $TEST_DIR`
> diff --git a/common/config b/common/config
> index a47e462c77..8153301483 100644
> --- a/common/config
> +++ b/common/config
> @@ -415,6 +415,9 @@ _mkfs_opts()
>  	btrfs)
>  		export MKFS_OPTIONS="$BTRFS_MKFS_OPTIONS"
>  		;;
> +	bcachefs)
> +		export MKFS_OPTIONS="--errors=panic"

I think this might be useful for bcachefs developers to find bugs
earlier, but not suitable for people like QA, as this may crash their
test machines and stop the whole test.

You could always set MKFS_OPTIONS to "--errors=panic" explicitly when
needed.

> +		;;
>  	*)
>  		;;
>  	esac
> diff --git a/common/dmlogwrites b/common/dmlogwrites
> index 573f4b8a56..668d49e995 100644
> --- a/common/dmlogwrites
> +++ b/common/dmlogwrites
> @@ -111,6 +111,13 @@ _log_writes_replay_log()
>  	[ -z "$_blkdev" ] && _fail \
>  	"block dev must be specified for _log_writes_replay_log"
>  
> +	if [ "$FSTYP" = "bcachefs" ]; then
> +		# bcachefs gets confused if we're replaying the history out of
> +		# order, and we see writes on the device from a newer point in
> +		# time than what the superblock points to:
> +		dd if=/dev/zero of=$SCRATCH_DEV bs=1M oflag=direct >& /dev/null

I don't know bcachefs internals, I'm not sure I understand this,
clearing the first 1M of SCRATCH_DEV seems to clear superblock, but I'm
still not sure why it's needed. Does wipefs work?

> +	fi
> +
>  	$here/src/log-writes/replay-log --log $LOGWRITES_DEV --find \
>  		--end-mark $_mark >> $seqres.full 2>&1
>  	[ $? -ne 0 ] && _fail "mark '$_mark' does not exist"
> diff --git a/common/quota b/common/quota
> index 32a9a55593..883a28a20d 100644
> --- a/common/quota
> +++ b/common/quota
> @@ -17,7 +17,7 @@ _require_quota()
>  	    _notrun "Installed kernel does not support quotas"
>  	fi
>  	;;
> -    gfs2|ocfs2)
> +    gfs2|ocfs2|bcachefs)
>  	;;
>      xfs)
>  	if [ ! -f /proc/fs/xfs/xqmstat ]; then
> @@ -278,7 +278,7 @@ _check_quota_usage()
>  
>  	VFS_QUOTA=0
>  	case $FSTYP in
> -	ext2|ext3|ext4|ext4dev|f2fs|reiserfs|gfs2)
> +	ext2|ext3|ext4|ext4dev|f2fs|reiserfs|gfs2|bcachefs)
>  		VFS_QUOTA=1
>  		quotaon -f -u -g $SCRATCH_MNT 2>/dev/null
>  		;;
> diff --git a/common/rc b/common/rc
> index 2cf550ec68..0e03846aeb 100644
> --- a/common/rc
> +++ b/common/rc
> @@ -334,6 +334,7 @@ _try_scratch_mount()
>  		return $?
>  	fi
>  	_mount -t $FSTYP `_scratch_mount_options $*`
> +	return

Seems not necessary.

>  }
>  
>  # mount scratch device with given options and _fail if mount fails
> @@ -667,6 +668,9 @@ _test_mkfs()
>      ext2|ext3|ext4)
>  	$MKFS_PROG -t $FSTYP -- -F $MKFS_OPTIONS $* $TEST_DEV
>  	;;
> +    bcachefs)
> +	$MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* $TEST_DEV
> +	;;

I think we could just use the default mkfs command below. The only
difference is dropping the "yes | " part, but that does nothing if mkfs
doesn't read "yes" or "no" from stdin.

>      *)
>  	yes | $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* $TEST_DEV
>  	;;
> @@ -706,6 +710,10 @@ _mkfs_dev()
>  	$MKFS_PROG -t $FSTYP -- -f $MKFS_OPTIONS $* \
>  		2>$tmp.mkfserr 1>$tmp.mkfsstd
>  	;;
> +    bcachefs)
> +	$MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* \
> +		2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
> +	;;

Same as above.

>      *)
>  	yes | $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* \
>  		2>$tmp.mkfserr 1>$tmp.mkfsstd
> @@ -803,6 +811,10 @@ _scratch_mkfs()
>  		mkfs_cmd="yes | $MKFS_PROG -t $FSTYP --"
>  		mkfs_filter="grep -v -e ^mkfs\.ocfs2"
>  		;;
> +	bcachefs)
> +		mkfs_cmd="$MKFS_PROG -t $FSTYP --"
> +		mkfs_filter="cat"
> +		;;

Same here.

>  	*)
>  		mkfs_cmd="yes | $MKFS_PROG -t $FSTYP --"
>  		mkfs_filter="cat"
> @@ -1065,6 +1077,9 @@ _scratch_mkfs_sized()
>  		fi
>  		export MOUNT_OPTIONS="-o size=$fssize $TMPFS_MOUNT_OPTIONS"
>  		;;
> +	bcachefs)
> +		$MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS --fs_size=$fssize --block_size=$blocksize $SCRATCH_DEV
> +		;;
>  	*)
>  		_notrun "Filesystem $FSTYP not supported in _scratch_mkfs_sized"
>  		;;
> @@ -1133,6 +1148,9 @@ _scratch_mkfs_blocksized()
>      ocfs2)
>  	yes | ${MKFS_PROG} -t $FSTYP -F $MKFS_OPTIONS -b $blocksize -C $blocksize $SCRATCH_DEV
>  	;;
> +    bcachefs)
> +	${MKFS_PROG}.$FSTYP $MKFS_OPTIONS --block_size=$blocksize $SCRATCH_DEV
> +	;;

Better to be consistent and use "${MKFS_PROG} -t $FSTYP ..." instead of
${MKFS_PROG}.$FSTYP

>      *)
>  	_notrun "Filesystem $FSTYP not supported in _scratch_mkfs_blocksized"
>  	;;
> @@ -1179,6 +1197,19 @@ _repair_scratch_fs()
>  	fi
>  	return $res
>          ;;
> +    bcachefs)
> +	fsck -t $FSTYP -n $SCRATCH_DEV 2>&1

_repair_scratch_fs() is supposed to actually fix the errors, does
"fsck -n" fix errors for bcachefs?

> +	res=$?
> +	case $res in
> +	0)
> +		res=0
> +		;;
> +	*)
> +		_dump_err2 "fsck.$FSTYP failed, err=$res"
> +		;;
> +	esac
> +	return $res
> +	;;
>      *)
>  	local dev=$SCRATCH_DEV
>  	local fstyp=$FSTYP
> diff --git a/tests/generic/042 b/tests/generic/042
> index 35727bcbc6..42919e2313 100755
> --- a/tests/generic/042
> +++ b/tests/generic/042
> @@ -63,7 +63,8 @@ _crashtest()
>  
>  	# We should /never/ see 0xCD in the file, because we wrote that pattern
>  	# to the filesystem image to expose stale data.
> -	if hexdump -v -e '/1 "%02X "' $file | grep -q "CD"; then
> +	# The file is not required to exist since we didn't sync before going down:
> +	if [[ -f $file ]] && hexdump -v -e '/1 "%02X "' $file | grep -q "CD"; then
>  		echo "Saw stale data!!!"
>  		hexdump $file
>  	fi

Updates for individual test should be in a separate patch.

> diff --git a/tests/generic/425 b/tests/generic/425
> index 51cbe1c67d..be2bc1b02e 100755
> --- a/tests/generic/425
> +++ b/tests/generic/425
> @@ -30,6 +30,9 @@ _cleanup()
>  
>  # real QA test starts here
>  _supported_fs generic
> +
> +[ $FSTYP = bcachefs ] && _notrun "bcachefs does not store xattrs in blocks"
> +
>  _require_scratch
>  _require_attrs
>  _require_xfs_io_command "fiemap" "-a"
> diff --git a/tests/generic/441 b/tests/generic/441
> index bedbcb0817..814387b2a9 100755
> --- a/tests/generic/441
> +++ b/tests/generic/441
> @@ -40,7 +40,7 @@ case $FSTYP in
>  	btrfs)
>  		_notrun "btrfs has a specialized test for this"
>  		;;
> -	ext3|ext4|xfs)
> +	ext3|ext4|xfs|bcachefs)
>  		# Do the more thorough test if we have a logdev
>  		_has_logdev && sflag=''
>  		;;
> diff --git a/tests/generic/482 b/tests/generic/482
> index 86941e8468..3cbe187f2e 100755
> --- a/tests/generic/482
> +++ b/tests/generic/482
> @@ -77,16 +77,29 @@ prev=$(_log_writes_mark_to_entry_number mkfs)
>  cur=$(_log_writes_find_next_fua $prev)
>  [ -z "$cur" ] && _fail "failed to locate next FUA write"
>  
> +if [ "$FSTYP" = "bcachefs" ]; then
> +    _dmthin_cleanup
> +    _dmthin_init $devsize $devsize $csize $lowspace
> +fi
> +
>  while [ ! -z "$cur" ]; do
>  	_log_writes_replay_log_range $cur $DMTHIN_VOL_DEV >> $seqres.full
>  
> -	# Here we need extra mount to replay the log, mainly for journal based
> -	# fs, as their fsck will report dirty log as error.
> -	# We don't care to preserve any data on the replay dev, as we can replay
> -	# back to the point we need, and in fact sometimes creating/deleting
> -	# snapshots repeatedly can be slower than replaying the log.
> -	_dmthin_mount
> -	_dmthin_check_fs
> +	if [ "$FSTYP" = "bcachefs" ]; then
> +	    # bcachefs will get confused if fsck does writes to replay the log,
> +	    # but then we replay writes from an earlier point in time on the
> +	    # same fs - but  fsck in -n mode won't do any writes:
> +	    _check_scratch_fs -n $DMTHIN_VOL_DEV
> +	else
> +	    # Here we need extra mount to replay the log, mainly for journal based
> +	    # fs, as their fsck will report dirty log as error.
> +	    # We don't care to preserve any data on the replay dev, as we can replay
> +	    # back to the point we need, and in fact sometimes creating/deleting
> +	    # snapshots repeatedly can be slower than replaying the log.
> +
> +	    _dmthin_mount
> +	    _dmthin_check_fs
> +	fi
>  
>  	prev=$cur
>  	cur=$(_log_writes_find_next_fua $(($cur + 1)))
> diff --git a/tests/generic/558 b/tests/generic/558
> index 4bed90e2a7..2eaa8f7686 100755
> --- a/tests/generic/558
> +++ b/tests/generic/558
> @@ -55,6 +55,8 @@ _scratch_mount
>  i=0
>  free_inode=`_get_free_inode $SCRATCH_MNT`
>  file_per_dir=1000
> +[ $FSTYP = bcachefs ] && file_per_dir=10000
> +

Some comments would be good.

Thanks,
Eryu

>  loop=$((free_inode / file_per_dir + 1))
>  mkdir -p $SCRATCH_MNT/testdir
>  
> -- 
> 2.31.1
Kent Overstreet May 23, 2021, 10:51 p.m. UTC | #2
On Sun, May 09, 2021 at 10:36:05PM +0800, Eryu Guan wrote:
> On Tue, Apr 27, 2021 at 12:44:17PM -0400, Kent Overstreet wrote:
> > From: Kent Overstreet <kmo@daterainc.com>
> 
> Better to add commit logs at least to give an example about how to setup
> fstests to test bcachefs.
> 
> You could always set MKFS_OPTIONS to "--errors=panic" explicitly when
> needed.

Forgot that was an option - doing that now.
> 
> > +		;;
> >  	*)
> >  		;;
> >  	esac
> > diff --git a/common/dmlogwrites b/common/dmlogwrites
> > index 573f4b8a56..668d49e995 100644
> > --- a/common/dmlogwrites
> > +++ b/common/dmlogwrites
> > @@ -111,6 +111,13 @@ _log_writes_replay_log()
> >  	[ -z "$_blkdev" ] && _fail \
> >  	"block dev must be specified for _log_writes_replay_log"
> >  
> > +	if [ "$FSTYP" = "bcachefs" ]; then
> > +		# bcachefs gets confused if we're replaying the history out of
> > +		# order, and we see writes on the device from a newer point in
> > +		# time than what the superblock points to:
> > +		dd if=/dev/zero of=$SCRATCH_DEV bs=1M oflag=direct >& /dev/null
> 
> I don't know bcachefs internals, I'm not sure I understand this,
> clearing the first 1M of SCRATCH_DEV seems to clear superblock, but I'm
> still not sure why it's needed. Does wipefs work?

It's not just the superblock we need to clear, it's really all metadata - the
journal, and btree nodes are also log structured in bcachefs. So 1M actually
isn't sufficient - the better solution would be to either

 - change the tests to check the markers in the log in the correct order, so
   we never see metadata from a future point in time, also making sure we don't
   do any writes to the filesystem when we're checking the different markers, or
 - just replay to a new dm-thin device

This is basically what I did for generic/482, the 1M zerout is really just a
hack for 455 and 457 and should probably be moved there, unless you've got
another suggestion.

> > diff --git a/common/rc b/common/rc
> > index 2cf550ec68..0e03846aeb 100644
> > --- a/common/rc
> > +++ b/common/rc
> > @@ -334,6 +334,7 @@ _try_scratch_mount()
> >  		return $?
> >  	fi
> >  	_mount -t $FSTYP `_scratch_mount_options $*`
> > +	return
> 
> Seems not necessary.

Not sure how that got in, dropped it.

> > +    bcachefs)
> > +	$MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* $TEST_DEV
> > +	;;
> 
> I think we could just use the default mkfs command below. The only
> difference is dropping the "yes | " part, but that does nothing if mkfs
> doesn't read "yes" or "no" from stdin.

That dates from when my test environment had SIGPIPE set up wrong (systemd!),
it's fixed now so I've dropped these.
> >      *)
> >  	_notrun "Filesystem $FSTYP not supported in _scratch_mkfs_blocksized"
> >  	;;
> > @@ -1179,6 +1197,19 @@ _repair_scratch_fs()
> >  	fi
> >  	return $res
> >          ;;
> > +    bcachefs)
> > +	fsck -t $FSTYP -n $SCRATCH_DEV 2>&1
> 
> _repair_scratch_fs() is supposed to actually fix the errors, does
> "fsck -n" fix errors for bcachefs?

No - but with bcachefs fsck finding errors _always_ indicates a bug, so for the
purposes of these tests I think this is the right thing to do - I don't want the
tests to pass if fsck is finding and fixing errors.

> > diff --git a/tests/generic/042 b/tests/generic/042
> > index 35727bcbc6..42919e2313 100755
> > --- a/tests/generic/042
> > +++ b/tests/generic/042
> > @@ -63,7 +63,8 @@ _crashtest()
> >  
> >  	# We should /never/ see 0xCD in the file, because we wrote that pattern
> >  	# to the filesystem image to expose stale data.
> > -	if hexdump -v -e '/1 "%02X "' $file | grep -q "CD"; then
> > +	# The file is not required to exist since we didn't sync before going down:
> > +	if [[ -f $file ]] && hexdump -v -e '/1 "%02X "' $file | grep -q "CD"; then
> >  		echo "Saw stale data!!!"
> >  		hexdump $file
> >  	fi
> 
> Updates for individual test should be in a separate patch.

Ok, I'll split those out.
Eryu Guan May 24, 2021, 3:56 a.m. UTC | #3
On Sun, May 23, 2021 at 06:51:49PM -0400, Kent Overstreet wrote:
[snip]

> > >  	;;
> > > @@ -1179,6 +1197,19 @@ _repair_scratch_fs()
> > >  	fi
> > >  	return $res
> > >          ;;
> > > +    bcachefs)
> > > +	fsck -t $FSTYP -n $SCRATCH_DEV 2>&1
> > 
> > _repair_scratch_fs() is supposed to actually fix the errors, does
> > "fsck -n" fix errors for bcachefs?
> 
> No - but with bcachefs fsck finding errors _always_ indicates a bug, so for the
> purposes of these tests I think this is the right thing to do - I don't want the
> tests to pass if fsck is finding and fixing errors.

Then _check_scratch_fs() should be used instead, which will fail the
test if any fsck finds any corruptions. _repair_scratch_fs() is meant to
fix errors, and only report failure when there's unfixable errors.

Thanks,
Eryu

> 
> > > diff --git a/tests/generic/042 b/tests/generic/042
> > > index 35727bcbc6..42919e2313 100755
> > > --- a/tests/generic/042
> > > +++ b/tests/generic/042
> > > @@ -63,7 +63,8 @@ _crashtest()
> > >  
> > >  	# We should /never/ see 0xCD in the file, because we wrote that pattern
> > >  	# to the filesystem image to expose stale data.
> > > -	if hexdump -v -e '/1 "%02X "' $file | grep -q "CD"; then
> > > +	# The file is not required to exist since we didn't sync before going down:
> > > +	if [[ -f $file ]] && hexdump -v -e '/1 "%02X "' $file | grep -q "CD"; then
> > >  		echo "Saw stale data!!!"
> > >  		hexdump $file
> > >  	fi
> > 
> > Updates for individual test should be in a separate patch.
> 
> Ok, I'll split those out.
Kent Overstreet May 24, 2021, 4:04 a.m. UTC | #4
On Mon, May 24, 2021 at 11:56:04AM +0800, Eryu Guan wrote:
> On Sun, May 23, 2021 at 06:51:49PM -0400, Kent Overstreet wrote:
> [snip]
> 
> > > >  	;;
> > > > @@ -1179,6 +1197,19 @@ _repair_scratch_fs()
> > > >  	fi
> > > >  	return $res
> > > >          ;;
> > > > +    bcachefs)
> > > > +	fsck -t $FSTYP -n $SCRATCH_DEV 2>&1
> > > 
> > > _repair_scratch_fs() is supposed to actually fix the errors, does
> > > "fsck -n" fix errors for bcachefs?
> > 
> > No - but with bcachefs fsck finding errors _always_ indicates a bug, so for the
> > purposes of these tests I think this is the right thing to do - I don't want the
> > tests to pass if fsck is finding and fixing errors.
> 
> Then _check_scratch_fs() should be used instead, which will fail the
> test if any fsck finds any corruptions. _repair_scratch_fs() is meant to
> fix errors, and only report failure when there's unfixable errors.

I see no reason to make such a change to generic tests that were written for
other filesystems, when this gets me exactly what I want.
Eryu Guan May 24, 2021, 4:22 a.m. UTC | #5
On Mon, May 24, 2021 at 12:04:32AM -0400, Kent Overstreet wrote:
> On Mon, May 24, 2021 at 11:56:04AM +0800, Eryu Guan wrote:
> > On Sun, May 23, 2021 at 06:51:49PM -0400, Kent Overstreet wrote:
> > [snip]
> > 
> > > > >  	;;
> > > > > @@ -1179,6 +1197,19 @@ _repair_scratch_fs()
> > > > >  	fi
> > > > >  	return $res
> > > > >          ;;
> > > > > +    bcachefs)
> > > > > +	fsck -t $FSTYP -n $SCRATCH_DEV 2>&1
> > > > 
> > > > _repair_scratch_fs() is supposed to actually fix the errors, does
> > > > "fsck -n" fix errors for bcachefs?
> > > 
> > > No - but with bcachefs fsck finding errors _always_ indicates a bug, so for the
> > > purposes of these tests I think this is the right thing to do - I don't want the
> > > tests to pass if fsck is finding and fixing errors.
> > 
> > Then _check_scratch_fs() should be used instead, which will fail the
> > test if any fsck finds any corruptions. _repair_scratch_fs() is meant to
> > fix errors, and only report failure when there's unfixable errors.
> 
> I see no reason to make such a change to generic tests that were written for
> other filesystems, when this gets me exactly what I want.

Oh, I noticed that "with bcachefs fsck finding errors _always_ indicates
a bug" now.. Then I think using fsck -n is fine here, but better with
comments to describe why this is ok for bcachefs.

Also, we could just use _check_scratch_fs here instead of the open-coded
fsck command. As _check_scratch_fs calls _check_generic_filesystem()
which calls fsck -n internally, and handles mount/umount device
correctly and prints pretty log if there's any errors.

Thanks,
Eryu
Kent Overstreet May 24, 2021, 4:48 a.m. UTC | #6
On Mon, May 24, 2021 at 12:22:53PM +0800, Eryu Guan wrote:
> Oh, I noticed that "with bcachefs fsck finding errors _always_ indicates
> a bug" now.. Then I think using fsck -n is fine here, but better with
> comments to describe why this is ok for bcachefs.
> 
> Also, we could just use _check_scratch_fs here instead of the open-coded
> fsck command. As _check_scratch_fs calls _check_generic_filesystem()
> which calls fsck -n internally, and handles mount/umount device
> correctly and prints pretty log if there's any errors.

That should work.
diff mbox series

Patch

diff --git a/common/attr b/common/attr
index 669909d600..42ceab9233 100644
--- a/common/attr
+++ b/common/attr
@@ -33,6 +33,9 @@  _acl_get_max()
 			echo 506
 		fi
 		;;
+	bcachefs)
+		echo 251
+		;;
 	*)
 		echo 0
 		;;
@@ -273,6 +276,9 @@  pvfs2)
 9p|ceph|nfs)
 	MAX_ATTRVAL_SIZE=65536
 	;;
+bcachefs)
+	MAX_ATTRVAL_SIZE=1024
+	;;
 *)
 	# Assume max ~1 block of attrs
 	BLOCK_SIZE=`_get_block_size $TEST_DIR`
diff --git a/common/config b/common/config
index a47e462c77..8153301483 100644
--- a/common/config
+++ b/common/config
@@ -415,6 +415,9 @@  _mkfs_opts()
 	btrfs)
 		export MKFS_OPTIONS="$BTRFS_MKFS_OPTIONS"
 		;;
+	bcachefs)
+		export MKFS_OPTIONS="--errors=panic"
+		;;
 	*)
 		;;
 	esac
diff --git a/common/dmlogwrites b/common/dmlogwrites
index 573f4b8a56..668d49e995 100644
--- a/common/dmlogwrites
+++ b/common/dmlogwrites
@@ -111,6 +111,13 @@  _log_writes_replay_log()
 	[ -z "$_blkdev" ] && _fail \
 	"block dev must be specified for _log_writes_replay_log"
 
+	if [ "$FSTYP" = "bcachefs" ]; then
+		# bcachefs gets confused if we're replaying the history out of
+		# order, and we see writes on the device from a newer point in
+		# time than what the superblock points to:
+		dd if=/dev/zero of=$SCRATCH_DEV bs=1M oflag=direct >& /dev/null
+	fi
+
 	$here/src/log-writes/replay-log --log $LOGWRITES_DEV --find \
 		--end-mark $_mark >> $seqres.full 2>&1
 	[ $? -ne 0 ] && _fail "mark '$_mark' does not exist"
diff --git a/common/quota b/common/quota
index 32a9a55593..883a28a20d 100644
--- a/common/quota
+++ b/common/quota
@@ -17,7 +17,7 @@  _require_quota()
 	    _notrun "Installed kernel does not support quotas"
 	fi
 	;;
-    gfs2|ocfs2)
+    gfs2|ocfs2|bcachefs)
 	;;
     xfs)
 	if [ ! -f /proc/fs/xfs/xqmstat ]; then
@@ -278,7 +278,7 @@  _check_quota_usage()
 
 	VFS_QUOTA=0
 	case $FSTYP in
-	ext2|ext3|ext4|ext4dev|f2fs|reiserfs|gfs2)
+	ext2|ext3|ext4|ext4dev|f2fs|reiserfs|gfs2|bcachefs)
 		VFS_QUOTA=1
 		quotaon -f -u -g $SCRATCH_MNT 2>/dev/null
 		;;
diff --git a/common/rc b/common/rc
index 2cf550ec68..0e03846aeb 100644
--- a/common/rc
+++ b/common/rc
@@ -334,6 +334,7 @@  _try_scratch_mount()
 		return $?
 	fi
 	_mount -t $FSTYP `_scratch_mount_options $*`
+	return
 }
 
 # mount scratch device with given options and _fail if mount fails
@@ -667,6 +668,9 @@  _test_mkfs()
     ext2|ext3|ext4)
 	$MKFS_PROG -t $FSTYP -- -F $MKFS_OPTIONS $* $TEST_DEV
 	;;
+    bcachefs)
+	$MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* $TEST_DEV
+	;;
     *)
 	yes | $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* $TEST_DEV
 	;;
@@ -706,6 +710,10 @@  _mkfs_dev()
 	$MKFS_PROG -t $FSTYP -- -f $MKFS_OPTIONS $* \
 		2>$tmp.mkfserr 1>$tmp.mkfsstd
 	;;
+    bcachefs)
+	$MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* \
+		2>$tmp_dir.mkfserr 1>$tmp_dir.mkfsstd
+	;;
     *)
 	yes | $MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS $* \
 		2>$tmp.mkfserr 1>$tmp.mkfsstd
@@ -803,6 +811,10 @@  _scratch_mkfs()
 		mkfs_cmd="yes | $MKFS_PROG -t $FSTYP --"
 		mkfs_filter="grep -v -e ^mkfs\.ocfs2"
 		;;
+	bcachefs)
+		mkfs_cmd="$MKFS_PROG -t $FSTYP --"
+		mkfs_filter="cat"
+		;;
 	*)
 		mkfs_cmd="yes | $MKFS_PROG -t $FSTYP --"
 		mkfs_filter="cat"
@@ -1065,6 +1077,9 @@  _scratch_mkfs_sized()
 		fi
 		export MOUNT_OPTIONS="-o size=$fssize $TMPFS_MOUNT_OPTIONS"
 		;;
+	bcachefs)
+		$MKFS_PROG -t $FSTYP -- $MKFS_OPTIONS --fs_size=$fssize --block_size=$blocksize $SCRATCH_DEV
+		;;
 	*)
 		_notrun "Filesystem $FSTYP not supported in _scratch_mkfs_sized"
 		;;
@@ -1133,6 +1148,9 @@  _scratch_mkfs_blocksized()
     ocfs2)
 	yes | ${MKFS_PROG} -t $FSTYP -F $MKFS_OPTIONS -b $blocksize -C $blocksize $SCRATCH_DEV
 	;;
+    bcachefs)
+	${MKFS_PROG}.$FSTYP $MKFS_OPTIONS --block_size=$blocksize $SCRATCH_DEV
+	;;
     *)
 	_notrun "Filesystem $FSTYP not supported in _scratch_mkfs_blocksized"
 	;;
@@ -1179,6 +1197,19 @@  _repair_scratch_fs()
 	fi
 	return $res
         ;;
+    bcachefs)
+	fsck -t $FSTYP -n $SCRATCH_DEV 2>&1
+	res=$?
+	case $res in
+	0)
+		res=0
+		;;
+	*)
+		_dump_err2 "fsck.$FSTYP failed, err=$res"
+		;;
+	esac
+	return $res
+	;;
     *)
 	local dev=$SCRATCH_DEV
 	local fstyp=$FSTYP
diff --git a/tests/generic/042 b/tests/generic/042
index 35727bcbc6..42919e2313 100755
--- a/tests/generic/042
+++ b/tests/generic/042
@@ -63,7 +63,8 @@  _crashtest()
 
 	# We should /never/ see 0xCD in the file, because we wrote that pattern
 	# to the filesystem image to expose stale data.
-	if hexdump -v -e '/1 "%02X "' $file | grep -q "CD"; then
+	# The file is not required to exist since we didn't sync before going down:
+	if [[ -f $file ]] && hexdump -v -e '/1 "%02X "' $file | grep -q "CD"; then
 		echo "Saw stale data!!!"
 		hexdump $file
 	fi
diff --git a/tests/generic/425 b/tests/generic/425
index 51cbe1c67d..be2bc1b02e 100755
--- a/tests/generic/425
+++ b/tests/generic/425
@@ -30,6 +30,9 @@  _cleanup()
 
 # real QA test starts here
 _supported_fs generic
+
+[ $FSTYP = bcachefs ] && _notrun "bcachefs does not store xattrs in blocks"
+
 _require_scratch
 _require_attrs
 _require_xfs_io_command "fiemap" "-a"
diff --git a/tests/generic/441 b/tests/generic/441
index bedbcb0817..814387b2a9 100755
--- a/tests/generic/441
+++ b/tests/generic/441
@@ -40,7 +40,7 @@  case $FSTYP in
 	btrfs)
 		_notrun "btrfs has a specialized test for this"
 		;;
-	ext3|ext4|xfs)
+	ext3|ext4|xfs|bcachefs)
 		# Do the more thorough test if we have a logdev
 		_has_logdev && sflag=''
 		;;
diff --git a/tests/generic/482 b/tests/generic/482
index 86941e8468..3cbe187f2e 100755
--- a/tests/generic/482
+++ b/tests/generic/482
@@ -77,16 +77,29 @@  prev=$(_log_writes_mark_to_entry_number mkfs)
 cur=$(_log_writes_find_next_fua $prev)
 [ -z "$cur" ] && _fail "failed to locate next FUA write"
 
+if [ "$FSTYP" = "bcachefs" ]; then
+    _dmthin_cleanup
+    _dmthin_init $devsize $devsize $csize $lowspace
+fi
+
 while [ ! -z "$cur" ]; do
 	_log_writes_replay_log_range $cur $DMTHIN_VOL_DEV >> $seqres.full
 
-	# Here we need extra mount to replay the log, mainly for journal based
-	# fs, as their fsck will report dirty log as error.
-	# We don't care to preserve any data on the replay dev, as we can replay
-	# back to the point we need, and in fact sometimes creating/deleting
-	# snapshots repeatedly can be slower than replaying the log.
-	_dmthin_mount
-	_dmthin_check_fs
+	if [ "$FSTYP" = "bcachefs" ]; then
+	    # bcachefs will get confused if fsck does writes to replay the log,
+	    # but then we replay writes from an earlier point in time on the
+	    # same fs - but  fsck in -n mode won't do any writes:
+	    _check_scratch_fs -n $DMTHIN_VOL_DEV
+	else
+	    # Here we need extra mount to replay the log, mainly for journal based
+	    # fs, as their fsck will report dirty log as error.
+	    # We don't care to preserve any data on the replay dev, as we can replay
+	    # back to the point we need, and in fact sometimes creating/deleting
+	    # snapshots repeatedly can be slower than replaying the log.
+
+	    _dmthin_mount
+	    _dmthin_check_fs
+	fi
 
 	prev=$cur
 	cur=$(_log_writes_find_next_fua $(($cur + 1)))
diff --git a/tests/generic/558 b/tests/generic/558
index 4bed90e2a7..2eaa8f7686 100755
--- a/tests/generic/558
+++ b/tests/generic/558
@@ -55,6 +55,8 @@  _scratch_mount
 i=0
 free_inode=`_get_free_inode $SCRATCH_MNT`
 file_per_dir=1000
+[ $FSTYP = bcachefs ] && file_per_dir=10000
+
 loop=$((free_inode / file_per_dir + 1))
 mkdir -p $SCRATCH_MNT/testdir