#!/usr/bin/env bash . $(dirname $(readlink -e ${BASH_SOURCE[0]}))/bcachefs-test-libs.sh require-kernel-config BCACHEFS_TESTS require-kernel-config BCACHEFS_QUOTA require-kernel-config MD require-kernel-config BLK_DEV_DM require-kernel-config DM_FLAKEY # migrate tests: require-kernel-config BLK_DEV_WRITE_MOUNTED config-scratch-devs 4G config-scratch-devs 4G test_wipe_btrfs() { set_watchdog 10 mkfs.btrfs -f ${ktest_scratch_dev[0]} bcachefs format -f ${ktest_scratch_dev[0]} ! mount -t btrfs ${ktest_scratch_dev[0]} /mnt } test_stress_ng() { set_watchdog 300 setup_tracing 'bcachefs:*' run_quiet "" bcachefs format --no_initialize --version=11 -f ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt cd /mnt stress-ng -v -t 60 --class filesystem --all 1 || true stress-ng -v -t 60 --class filesystem --all 2 || true cd /root umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_punch() { set_watchdog 10 run_quiet "" bcachefs format -f --errors=panic ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt xfs_io -f /mnt/foo -c "pwrite -S 0x55 0 16384" xfs_io -f /mnt/foo -c "fsync" xfs_io -f /mnt/foo -c "fpunch 4095 4097" md5sum /mnt/foo umount /mnt mount -t bcachefs ${ktest_scratch_dev[0]} /mnt md5sum /mnt/foo umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_remount_ro_rw() { set_watchdog 10 run_quiet "" bcachefs format -f --errors=panic ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt echo "test: remount-ro" mount -o remount,ro /mnt ! touch /mnt/foo echo "test: remount-rw" mount -o remount,rw /mnt touch /mnt/bar umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_mount_again_after_ebusy() { set_watchdog 10 run_quiet "" bcachefs format -f --errors=panic ${ktest_scratch_dev[0]} echo "test: mount ro" mount -t bcachefs -o ro ${ktest_scratch_dev[0]} /mnt mkdir -p /mnt2 echo "test: try mount rw (1)" ! mount -t bcachefs -o rw ${ktest_scratch_dev[0]} /mnt2 echo "test: try mount rw (2)" ! mount -t bcachefs -o rw ${ktest_scratch_dev[0]} /mnt2 umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_mount_options() { local dev=${ktest_scratch_dev[0]} set_watchdog 10 run_quiet "" bcachefs format -f --errors=panic $dev echo "test: valid mount options" mount -t bcachefs -o metadata_checksum=crc64,metadata_target=$(basename $dev) $dev /mnt mount -t bcachefs | grep --quiet metadata_checksum mount -t bcachefs | grep --quiet metadata_target echo "test: valid remount options" mount -o remount,ro,errors=continue /mnt mount -t bcachefs | grep --quiet metadata_target mount -t bcachefs | grep --quiet continue mount -t bcachefs | grep --quiet ro umount /mnt echo "test: invalid mount options" ! mount -t bcachefs -o metadata_checksum=invalid $dev /mnt ! mount -t bcachefs -o promote_target=$(basename $dev),metadata_target=not_a_device $dev /mnt echo "test: invalid remount options" mount -t bcachefs $dev /mnt ! mount -o remount,promote_target=not_a_device /mnt ! mount -o remount,metadata_replicas=not_a_number /mnt umount /mnt bcachefs fsck -ny $dev bcachefs_test_end_checks $dev } test_extent_merge2() { local p=/sys/module/bcachefs/parameters/debug_check_iterators set_watchdog 10 [[ -f $p ]] && echo 1 > $p run_quiet "" bcachefs format -f --errors=panic ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt fallocate -o 0 -l 4096 /mnt/foo fallocate -o 4096 -l 4096 /mnt/foo umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} [[ -f $p ]] && echo 0 > $p true } test_extent_repair_overlapping() { set_watchdog 10 run_quiet "" bcachefs format -f --errors=panic ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt truncate -s1M /mnt/foo inum=$(ls -li /mnt/foo|cut -d\ -f1) bcachefs subvolume snapshot /mnt/snap.0 bcachefs subvolume snapshot /mnt/snap.1 ln -sf /sys/fs/bcachefs/*/perf_test p echo test_extent_create_overlapping $inum 1 > p umount /mnt mount -t bcachefs -o fsck,fix_errors ${ktest_scratch_dev[0]} /mnt umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_reflink3() { # reproducer for a common filesystem reflink bug # based on zfs reflink corruption reproducer[1] # apparently also exposed by portage's reflink file copy implementation[2][3] # [1] https://gist.github.com/tonyhutter/d69f305508ae3b7ff6e9263b22031a84#file-reproducer-sh # [2] https://wiki.gentoo.org/wiki/User:Sam/Memorable_bugs_I_like_to_reference#Bugs_found_by_Portage.27s_native_file_copying # [3] https://github.com/openzfs/zfs/issues/11900#issuecomment-927568640 set_watchdog 60 run_quiet "" bcachefs format -f --errors=panic ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt prefix="reproducer_${BASHPID}_" dd if=/dev/urandom of=${prefix}0 bs=1M count=1 status=none end=1000 h=0 for i in `seq 1 $end` ; do j=$((i + 1)) cp ${prefix}$h ${prefix}$i cp --reflink=never ${prefix}$i ${prefix}$j diff ${prefix}0 ${prefix}$i h=$((h + 1)) done for i in `seq 1 2 $end` ; do rm ${prefix}$i done umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_reflink2() { set_watchdog 10 bcachefs_antagonist run_quiet "" bcachefs format -f ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt dd if=/dev/urandom of=/mnt/foo bs=16k count=1 oflag=direct cp --reflink /mnt/foo /mnt/foo2 cp --reflink /mnt/foo /mnt/foo3 cp --reflink /mnt/foo /mnt/foo4 cp --reflink /mnt/foo /mnt/foo5 cp --reflink /mnt/foo /mnt/foo6 cat /sys/kernel/debug/bcachefs/*/btrees/reflink/keys dd if=/dev/urandom of=/mnt/foo2 bs=4k oflag=direct conv=notrunc count=1 dd if=/dev/urandom of=/mnt/foo3 bs=4k oflag=direct conv=notrunc count=1 seek=1 dd if=/dev/urandom of=/mnt/foo4 bs=4k oflag=direct conv=notrunc count=1 seek=3 dd if=/dev/urandom of=/mnt/foo5 bs=4k oflag=direct conv=notrunc count=2 dd if=/dev/urandom of=/mnt/foo6 bs=4k oflag=direct conv=notrunc count=1 seek=3 dd if=/dev/urandom of=/mnt/foo6 bs=4k oflag=direct conv=notrunc count=1 seek=2 cat /sys/kernel/debug/bcachefs/*/btrees/reflink/keys cat /sys/kernel/debug/bcachefs/*/btrees/reflink/keys|wc -l rm /mnt/foo* cat /sys/kernel/debug/bcachefs/*/btrees/reflink/keys|wc -l umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_reflink() { set_watchdog 60 run_quiet "" bcachefs format -f --errors=panic ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt run_fio_randrw --filesize=1000M & while [[ ! -f /mnt/fiotest ]]; do sleep 1 done for i in `seq 0 10`; do sleep 0.5 cp --reflink /mnt/fiotest /mnt/fiotest2 rm /mnt/fiotest2 done wait cat /sys/kernel/debug/bcachefs/*/btrees/reflink/keys|wc -l rm /mnt/fiotest* nr_left=`cat /sys/kernel/debug/bcachefs/*/btrees/reflink/keys|wc -l` echo "nr_left: $nr_left" [[ $nr_left = 0 ]] umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_fio_raw() { set_watchdog 120 fio --eta=always \ --exitall_on_error=1 \ --randrepeat=0 \ --ioengine=libaio \ --iodepth=64 \ --iodepth_batch=16 \ --direct=1 \ --numjobs=1 \ --filename=${ktest_scratch_dev[0]} \ --name=randread \ --rw=randread \ --size=40G \ --bs=4k } test_rewrite_old_nodes() { set_watchdog 60 run_quiet "" bcachefs format -f --no_initialize --version=10 ${ktest_scratch_dev[0]} bcachefs show-super ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt dd if=/dev/zero of=/mnt/foo bs=4k count=65536 oflag=direct umount /mnt bcachefs show-super ${ktest_scratch_dev[0]} bcachefs fsck ${ktest_scratch_dev[0]} bcachefs show-super ${ktest_scratch_dev[0]} mount -t bcachefs -o version_upgrade=incompatible ${ktest_scratch_dev[0]} /mnt bcachefs data job rewrite_old_nodes /mnt umount /mnt bcachefs show-super ${ktest_scratch_dev[0]} bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_merge_torture_flakey() { set_watchdog 600 local loops=$((($ktest_priority + 1) * 3)) local n=40M local BLK_DEV_SIZE=`blockdev --getsz ${ktest_scratch_dev[0]}` local FLAKEY_TABLE="0 $BLK_DEV_SIZE flakey ${ktest_scratch_dev[0]} 0 180 0" local FLAKEY_TABLE_ERROR="0 $BLK_DEV_SIZE flakey ${ktest_scratch_dev[0]} 0 0 180 1 error_writes" dmsetup create flakey --table "$FLAKEY_TABLE" set_dm_table() { dmsetup suspend flakey echo "$@"|dmsetup load flakey dmsetup resume flakey } run_quiet "" bcachefs format -f --btree_node_size=32k --errors=panic /dev/mapper/flakey for i in `seq 0 $loops`; do echo "loop: $i" mount -t bcachefs -o fsck /dev/mapper/flakey /mnt echo seq_delete $n 1 > /sys/fs/bcachefs/*/perf_test echo -n "nodes: " grep "^l " /sys/kernel/debug/bcachefs/*/btrees/xattrs/formats|wc -l df -h /mnt echo "inserting keys" echo seq_insert $n 1 > /sys/fs/bcachefs/*/perf_test & sleep 10 echo "starting write errors" echo "enabling errors" set_dm_table "$FLAKEY_TABLE_ERROR" wait umount /mnt echo "disabling errors" set_dm_table "$FLAKEY_TABLE" mount -t bcachefs -o fsck /dev/mapper/flakey /mnt echo seq_delete $n 1 > /sys/fs/bcachefs/*/perf_test & sleep 2 echo "enabling errors" set_dm_table "$FLAKEY_TABLE_ERROR" wait umount /mnt echo "disabling errors" set_dm_table "$FLAKEY_TABLE" done dmsetup remove flakey bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } # Disabled, because currently OOMs d_test_merge_torture() { setup_tracing local loops=$((($ktest_priority + 1) * 3)) local n=10M run_quiet "" bcachefs format -f --errors=panic --btree_node_size=8k --no_initialize ${ktest_scratch_dev[0]} for i in `seq 0 $loops`; do mount -t bcachefs -o fsck ${ktest_scratch_dev[0]} /mnt echo "loop: $i" echo rand_insert $n 1 > /sys/fs/bcachefs/*/perf_test df -h /mnt echo rand_delete $n 1 > /sys/fs/bcachefs/*/perf_test echo -n "nodes: " grep "^l " /sys/kernel/debug/bcachefs/*/xattrs/formats|wc -l df -h /mnt umount /mnt done } test_make_files() { set_watchdog 30 run_quiet "" bcachefs format -f ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt echo 3 > /proc/sys/vm/drop_caches free -m for i in `seq 0 1`; do echo -n > /mnt/$i done free -m echo 3 > /proc/sys/vm/drop_caches free -m umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_journal_resize() { set_watchdog 30 run_quiet "" bcachefs format -f ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt run_fio_randrw --filesize=2G & sleep 4 bcachefs device resize-journal ${ktest_scratch_dev[0]} 1G wait umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_drop_alloc() { set_watchdog 120 run_quiet "" bcachefs format -f ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt run_fio_randrw --filesize=2G umount /mnt mount -t bcachefs -o fsck ${ktest_scratch_dev[0]} /mnt umount /mnt echo "reconstructing alloc:" mount -t bcachefs -o reconstruct_alloc ${ktest_scratch_dev[0]} /mnt umount /mnt mount -t bcachefs -o fsck ${ktest_scratch_dev[0]} /mnt umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_reflink_inline_data() { set_watchdog 30 run_quiet "" bcachefs format -f ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt dd if=/dev/urandom of=/root/foo bs=256 count=1 cp /root/foo /mnt/foo1 cp /mnt/foo1 /mnt/foo2 cp --reflink /mnt/foo2 /mnt/foo3 md5sum /root/foo /mnt/foo* umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_split_compressed() { set_watchdog 30 run_quiet "" bcachefs format -f --compression=zstd ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt # Test that splitting of compressed extents is working correctly: dd if=/dev/zero of=/mnt/foo bs=128k count=1 oflag=direct dd if=/dev/urandom of=/mnt/foo bs=4k count=1 seek=1 oflag=direct conv=notrunc umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_fcollapse() { set_watchdog 30 run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt dd if=/dev/zero of=/mnt/foo bs=4k count=4 oflag=direct echo "before fcollapse" cat /sys/kernel/debug/bcachefs/*/btrees/extents/keys ls -l /mnt/foo echo xfs_io -c "fcollapse 4k 2k" /mnt/foo echo "after fcollapse" cat /sys/kernel/debug/bcachefs/*/btrees/extents/keys ls -l /mnt/foo echo umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_finsert() { set_watchdog 30 run_quiet "" bcachefs format -f ${ktest_scratch_dev[0]} mount -t bcachefs -o fsck ${ktest_scratch_dev[0]} /mnt dd if=/dev/zero of=/mnt/foo bs=64k count=1 oflag=direct cat /sys/kernel/debug/bcachefs/*/btrees/extents/keys xfs_io -c "finsert 1024 1024" /mnt/foo umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_key_merge() { set_watchdog 30 run_quiet "" bcachefs format -f --data_checksum=none ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt dd if=/dev/zero of=/mnt/foo bs=8k count=128 oflag=direct NR=$(cat /sys/kernel/debug/bcachefs/*/btrees/extents/keys|wc -l) [[ $NR -eq 4 ]] umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_key_merge_csum() { set_watchdog 30 run_quiet "" bcachefs format -f --data_checksum=crc32c ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt dd if=/dev/urandom of=/mnt/foo bs=8k count=128 oflag=direct cat /mnt/foo > /dev/null NR=$(cat /sys/kernel/debug/bcachefs/*/btrees/extents/keys|wc -l) [[ $NR -le 16 ]] umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_reconstruct_alloc() { set_watchdog 120 run_quiet "" bcachefs format -f --btree_node_size=16k ${ktest_scratch_dev[0]} mount -t bcachefs -o reconstruct_alloc,fix_errors,fsck ${ktest_scratch_dev[0]} /mnt umount /mnt bcachefs fsck -n ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt run_fio_randrw umount /mnt echo "Running fsck --reconstruct_alloc" fsck.bcachefs -ny --reconstruct_alloc ${ktest_scratch_dev[0]} && rc=$? || rc=$? if (( $rc != 0 && $rc != 1 )); then echo "Bad exit status from fsck: $rc" exit 1 fi echo "Mounting with -o reconstruct_alloc" mount -t bcachefs -o reconstruct_alloc,fix_errors,fsck ${ktest_scratch_dev[0]} /mnt umount /mnt bcachefs fsck -n ${ktest_scratch_dev[0]} mount -t bcachefs -o fsck ${ktest_scratch_dev[0]} /mnt umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_recovery() { set_watchdog 30 run_quiet "" bcachefs format -f \ --errors=panic \ --encrypted --no_passphrase \ --bucket_size=64k \ ${ktest_scratch_dev[0]} for i in `seq 0 1`; do mount -t bcachefs ${ktest_scratch_dev[0]} /mnt dd if=/dev/zero of=/mnt/foo bs=4k count=8 oflag=direct dd if=/dev/zero of=/mnt/foo bs=4k count=8 oflag=direct sync #run_fio_randrw #fio --eta=always \ # --exitall_on_error=1 \ # --randrepeat=0 \ # --ioengine=libaio \ # --iodepth=64 \ # --iodepth_batch=16 \ # --direct=1 \ # --numjobs=1 \ # --filename=/mnt/fiotest \ # --filesize=15M \ # --name=randwrite \ # --rw=randwrite \ # --bsrange=4k-8k $ktest_dir/tests/fs/xfstests/src/godown -f /mnt umount /mnt done bcachefs fsck -nyk ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_lz4_zeros() { set_watchdog 30 run_quiet "" bcachefs format -f --errors=panic \ --compression=lz4 \ --data_checksum=none \ --bucket_size=2M \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt dd if=/dev/zero of=/mnt/foo bs=1M count=10 # XXX check disk space used umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_lz4_incompressible() { set_watchdog 120 run_quiet "" bcachefs format -f --errors=panic \ --compression=lz4 \ --data_checksum=none \ --bucket_size=2M \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt dd if=/dev/urandom of=/mnt/foo || true umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_lz4() { run_basic_fio_test \ --compression=lz4 \ ${ktest_scratch_dev[0]} } test_lz4_buffered() { set_watchdog 120 #bcachefs_antagonist run_quiet "" bcachefs format -f \ --errors=panic \ --compression=lz4 \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt echo starting copy cp -rx / /mnt/foo echo starting sync sync echo starting rm rm -rf /mnt/* umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_gzip() { run_basic_fio_test \ --compression=gzip \ ${ktest_scratch_dev[0]} } test_zstd() { run_basic_fio_test \ --compression=zstd \ ${ktest_scratch_dev[0]} } test_background_compression() { run_quiet "" bcachefs format -f \ --errors=panic \ --background_compression=zstd \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt echo zstd > /sys/fs/bcachefs/*/options/background_compression run_fio_randrw umount /mnt bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_rebalance_scan() { setup_tracing 'bcachefs:*' run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt dd if=/dev/zero of=/mnt/foo bs=1M count=8 oflag=direct sleep 0.5 echo zstd > /sys/fs/bcachefs/*/options/background_compression sleep 2 cat /sys/fs/bcachefs/*/compression_stats|grep zstd|grep -q '8.00 MiB' umount /mnt bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_compress_no_checksum() { run_basic_fio_test \ --compression=lz4 \ --metadata_checksum=none \ --data_checksum=none \ ${ktest_scratch_dev[0]} } test_no_checksum() { run_basic_fio_test \ --metadata_checksum=none \ --data_checksum=none \ ${ktest_scratch_dev[0]} } test_crc32c() { run_basic_fio_test \ --metadata_checksum=crc32c \ --data_checksum=crc32c \ ${ktest_scratch_dev[0]} } test_crc64() { run_basic_fio_test \ --metadata_checksum=crc64 \ --data_checksum=crc64 \ ${ktest_scratch_dev[0]} } test_xxhash() { run_basic_fio_test \ --metadata_checksum=xxhash \ --data_checksum=xxhash \ ${ktest_scratch_dev[0]} } test_crypto_locked_mnt() { echo foo|bcachefs format -f --encrypted ${ktest_scratch_dev[0]} echo foo|bcachefs unlock -k session ${ktest_scratch_dev[0]} mount -t bcachefs -o verbose ${ktest_scratch_dev[0]} /mnt umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_crypto() { run_basic_fio_test \ --encrypted --no_passphrase \ ${ktest_scratch_dev[0]} mount -t bcachefs -o fsck ${ktest_scratch_dev[0]} /mnt umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_crypto_lz4() { run_basic_fio_test \ --encrypted --no_passphrase \ --compression=lz4 \ ${ktest_scratch_dev[0]} } run_copygc_torture() { set_watchdog 2400 loops=$((($ktest_priority + 1) * 4)) bcachefs_antagonist run_quiet "" bcachefs format -f \ --errors=panic \ --data_checksum=none \ "$@" ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt fill_device /mnt/fiotest for i in $(seq 0 $loops); do run_fio_base \ --buffer_compress_percentage=50 \ \ --name=randwrite \ --stonewall \ --rw=randwrite \ --loops=$loops \ --bsrange=4k-128k cur_size=$(stat -c '%s' /mnt/fiotest) new_size=$(($cur_size - 1048576)) echo "truncating to $new_size" truncate --size=$new_size /mnt/fiotest done rm /mnt/fiotest expect_sysfs cache dirty_buckets 0 expect_sysfs cache dirty_data 0 expect_sysfs cache cached_buckets 0 expect_sysfs cache cached_data 0 umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_copygc_torture() { #run_copygc_torture --bucket_size=256k --btree_node_size=8k run_copygc_torture --bucket_size=32k --btree_node_size=32k } test_copygc_torture_no_checksum() { run_copygc_torture --bucket_size=256k --btree_node_size=16k --data_checksum=none } test_copygc_torture_lz4() { run_copygc_torture --bucket_size=256k --btree_node_size=16k --compression=lz4 } test_small_buckets() { run_basic_fio_test \ --bucket_size=32k \ ${ktest_scratch_dev[0]} } # Gets stuck due to only having 512 buckets test_large_buckets() { run_basic_fio_test \ --bucket_size=8M \ --data_checksum=none \ ${ktest_scratch_dev[0]} } test_small_nodes() { run_basic_fio_test \ --bucket_size=256k \ --btree_node_size=4k \ ${ktest_scratch_dev[0]} } d_test_crypto_passphrase() { bcachefs_antagonist echo ""|bcachefs format -f --encrypted ${ktest_scratch_dev[0]} echo ""|bcachefs unlock ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_partial_overwritten_extents() { set_watchdog 10 run_quiet "" bcachefs format -f \ --errors=panic \ --encrypted --no_passphrase \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt dd if=/dev/urandom of=/mnt/foo bs=32k count=1 skip=0 oflag=direct dd if=/mnt/foo of=/dev/null bs=4k count=8 skip=0 iflag=direct dd if=/dev/urandom of=/mnt/foo bs=32k count=1 skip=0 oflag=direct dd if=/dev/zero of=/mnt/foo bs=4k count=1 skip=0 oflag=direct conv=notrunc dd if=/mnt/foo of=/dev/null bs=4k count=8 skip=0 iflag=direct dd if=/dev/urandom of=/mnt/bar bs=32k count=1 skip=0 oflag=direct dd if=/dev/zero of=/mnt/bar bs=4k count=1 skip=7 oflag=direct conv=notrunc dd if=/mnt/bar of=/dev/null bs=4k count=8 skip=0 iflag=direct > /dev/null dd if=/dev/urandom of=/mnt/baz bs=32k count=1 skip=0 oflag=direct dd if=/dev/zero of=/mnt/baz bs=4k count=1 skip=0 oflag=direct conv=notrunc dd if=/dev/zero of=/mnt/baz bs=4k count=1 skip=7 oflag=direct conv=notrunc dd if=/mnt/baz of=/dev/null bs=4k count=8 skip=0 iflag=direct > /dev/null umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } # test the xattr interface for per-inode IO options: test_xattr() { set_watchdog 10 run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt mkdir /mnt/foo setfattr -n bcachefs.compression -v lz4 /mnt/foo getfattr -n bcachefs.compression /mnt/foo echo "checking xattr propagation to children" touch /mnt/foo/bar getfattr -n bcachefs_effective.compression /mnt/foo/bar echo "checking xattr deletion" setfattr -x bcachefs.compression /mnt/foo/bar #getfattr -n bcachefs.compression /mnt/foo/bar rsync -rX /mnt/foo/ /mnt/baz getfattr -R -m - -d /mnt umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_quota() { set_watchdog 10 bcachefs_antagonist run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs -o usrquota,grpquota,prjquota ${ktest_scratch_dev[0]} /mnt loops=$((($ktest_priority + 1) * 4)) run_fio_randrw rm /mnt/fiotest umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } # test nfs exports: require-kernel-config NFSD require-kernel-config NFSD_V4 test_nfs() { set_watchdog 10 mkdir /export1 /export2 run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /export2 echo "/export1 *(ro,insecure,all_squash,no_subtree_check)" >> /etc/exports echo "/export2 *(ro,insecure,all_squash,no_subtree_check)" >> /etc/exports exportfs -a exportfs -ua umount /export2 bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } # We should get this working at some point: d_test_suspend() { set_watchdog 10 #setup_tracing 'bcachefs:*' ( p="/sys/power" sleep 10 echo freezer > $p/pm_test echo freeze > $p/state #echo 1 > /sys/fs/bcachefs/suspend #s2ram --no_kms --force )& run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt if false; then run_dbench else bcachefs_antagonist run_stress fi bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_journal_torture() { set_watchdog 60 bcachefs_antagonist run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt #enable_memory_faults echo 1 > /sys/fs/bcachefs/*/options/journal_flush_delay run_fio_randrw #disable_memory_faults umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_online_resize() { set_watchdog 60 bcachefs_antagonist run_quiet "" bcachefs format -f \ --errors=panic \ --fs_size=1G \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt df -h /mnt bcachefs device resize ${ktest_scratch_dev[0]} df -h /mnt umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_offline_resize() { set_watchdog 60 bcachefs_antagonist run_quiet "" bcachefs format -f \ --errors=panic \ --fs_size=1G \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt df -h /mnt cat /proc/mounts umount /mnt bcachefs device resize ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt df -h /mnt umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } require-kernel-config BLK_DEV_DM test_offline_resize_lv() { set_watchdog 60 pvcreate -f ${ktest_scratch_dev[0]} vgcreate vg ${ktest_scratch_dev[0]} lvcreate -L 1G -n foo vg dev=/dev/vg/foo run_quiet "" bcachefs format -f \ --errors=panic \ $dev mount -t bcachefs $dev /mnt df -h /mnt cat /proc/mounts lvresize -L +1G $dev bcachefs device resize $dev df -h /mnt umount /mnt mount -t bcachefs $dev /mnt df -h /mnt umount /mnt vgremove -f vg } test_sysfs() { set_watchdog 10 run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt find -H /sys/fs/bcachefs/ -type f -perm -0400 -exec cat {} \; > /dev/null umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_debugfs() { set_watchdog 30 run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt dd if=/dev/zero of=/mnt/test1 bs=1k count=10240 oflag=direct dd if=/dev/zero of=/mnt/test2 bs=1k count=10240 oflag=direct find -H /sys/kernel/debug/bcachefs/ -type f -perm -0400 -exec cat {} \; > /dev/null umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_set_option() { set_watchdog 10 run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt bcachefs set-fs-option --compression=zstd ${ktest_scratch_dev[0]} cat /sys/fs/bcachefs/*/options/compression umount /mnt echo "Setting option on offline fs" bcachefs set-fs-option --compression=lz4 ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt cat /sys/fs/bcachefs/*/options/compression umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } disabled_test_swapfile() { run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt fallocate -l 1G /mnt/swapfile mkswap /mnt/swapfile swapon /mnt/swapfile swapoff /mnt/swapfile umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } prepare_source_fs() { local fstype=$1 # prevent errors using rsync to verify, from other tests that didn't clean up: rm -rf /mnt/* if [[ $fstype = ext4 ]]; then run_quiet "" mkfs.$fstype -F ${ktest_scratch_dev[0]} mount -t $fstype -o user_xattr ${ktest_scratch_dev[0]} /mnt else run_quiet "" mkfs.$fstype -f ${ktest_scratch_dev[0]} mount -t $fstype ${ktest_scratch_dev[0]} /mnt fi cp -a /usr /mnt for i in /mnt/usr/bin/*; do if [ ! -L $i ]; then ln $i ${i}-migrate2 fi setfattr -n user.foo -v test $i done } check_rsync_log() { # rsync itemized output # https://jhpce.jhu.edu/files/rsync-itemize-table/ # .: the item is not being updated (though it might have attributes that are being modified) # We don't expect any lines to start with anything other than a dot # Ideally the output should be empty, but the lost+found/ directory is # ignored and the mountpoints themselves could have a modified time # Sample expected output: # .d..t...... ./ # .d..t...... lost+found/ ! grep -v "cd+++++++++ lost+found/" $1| grep -E '^[^.]' } verify_trees_equal() { local dir1=$1 local dir2=$2 rsync --archive \ --acls \ --xattrs \ --checksum \ --hard-links \ --dry-run \ --itemize-changes \ $dir1/ $dir2/ > /root/rsynclog-build check_rsync_log /root/rsynclog-build } # build a filesystem from a source build_from_fs() { set_watchdog 180 prepare_source_fs $1 bcachefs format -f \ --source=/mnt ${ktest_scratch_dev[1]} echo "Attempting to mount bcachefs filesystem" if true; then mkdir -p /mnt2 mount -t bcachefs -o noexcl,nochanges,ro ${ktest_scratch_dev[1]} /mnt2 verify_trees_equal /mnt /mnt2 umount /mnt2 echo "rsync passed" fi umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[1]} bcachefs_test_end_checks ${ktest_scratch_dev[1]} } test_build_from_ext4() { build_from_fs ext4 } require-kernel-config XFS_FS test_build_from_xfs() { build_from_fs xfs } require-kernel-config BTRFS_FS test_build_from_btrfs() { build_from_fs btrfs } test_build_from_bcachefs() { build_from_fs bcachefs } # migrate from other filesystems in place: migrate_from_fs() { local fstype=$1 set_watchdog 180 prepare_source_fs $fstype bcachefs migrate \ --encrypted \ --no_passphrase \ -F -f /mnt | tee /root/migratelog offset=$(grep -oE 'sb=[[:digit:]]+' /root/migratelog|head -n1|sed -e 's/sb=//') umount /mnt fsck.$fstype -n ${ktest_scratch_dev[0]} echo "Attempting to mount bcachefs filesystem with superblock offset $offset" if true; then mkdir -p /mnt2 mount -t bcachefs -o noexcl,nochanges,ro,sb=$offset ${ktest_scratch_dev[0]} /mnt2 rsync --archive \ --acls \ --xattrs \ --checksum \ --hard-links \ --exclude=/bcachefs \ --dry-run \ --itemize-changes \ /mnt/ /mnt2/ > /root/rsynclog-migrate check_rsync_log /root/rsynclog-migrate umount /mnt2 echo "rsync passed" fi mount -t bcachefs -o sb=$offset ${ktest_scratch_dev[0]} /mnt umount /mnt echo "Creating default superblock" bcachefs migrate-superblock -d ${ktest_scratch_dev[0]} -o $offset mount -t bcachefs ${ktest_scratch_dev[0]} /mnt rm /mnt/old_migrated_filesystem umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_migrate_from_ext4() { migrate_from_fs ext4 } require-kernel-config XFS_FS test_migrate_from_xfs() { migrate_from_fs xfs } require-kernel-config BTRFS_FS test_migrate_from_btrfs() { migrate_from_fs btrfs } d_test_migrate_from_bcachefs() { migrate_from_fs bcachefs } # we don't currently have fault injection: d_test_init_faults() { setup_tracing 'bcachefs:*' run_quiet "" bcachefs format -f \ --errors=remount-ro \ ${ktest_scratch_dev[0]} # put some data on the filesystem mount -t bcachefs ${ktest_scratch_dev[0]} /mnt run_fio_randrw # dbench would be better, create a directory structure #run_dbench umount /mnt init_fault_fn() { set_faults "$1 enable" # should fail: ! mount -t bcachefs -o verbose ${ktest_scratch_dev[0]} /mnt } run_fault_injection_test bcachefs:bch_fs_init init_fault_fn run_fault_injection_test bcachefs:meta:read init_fault_fn } # we don't currently have fault injection: d_test_meta_write_faults() { setup_tracing 'bcachefs:*' run_quiet "" bcachefs format -f \ --errors=remount-ro \ ${ktest_scratch_dev[0]} meta_write_fault_fn() { mount -t bcachefs ${ktest_scratch_dev[0]} /mnt (sleep 2; set_faults "$1 enable") & # Should fail due to read only cache set ! run_fio # XXX: verify we've gone RO umount /mnt } run_fault_injection_test bcachefs:meta::write meta_write_fault_fn } test_long_name() { set_watchdog 20 run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt local i=1 local n="1" while touch /mnt/$n 2> /dev/null; do n="1$n" i=$(($i + 1)) done echo $i umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_many_files() { set_watchdog 60 run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt for i in {1..1000}; do touch /mnt/$i done umount /mnt mount -t bcachefs ${ktest_scratch_dev[0]} /mnt umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } disabled_test_invalid_keys() { echo 1 > /sys/module/bcachefs/parameters/inject_invalid_keys run_quiet "" bcachefs format -f \ --errors=continue \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt for i in {1..1000}; do touch /mnt/$i done umount /mnt mount -t bcachefs -o fix_errors ${ktest_scratch_dev[0]} /mnt umount /mnt echo 0 > /sys/module/bcachefs/parameters/inject_invalid_keys } test_buffered_reads() { set_watchdog 60 run_quiet "" bcachefs format -f \ --errors=panic \ --bucket_size=8M \ --data_checksum=none \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt dd if=/dev/zero of=/mnt/foo bs=1M oflag=direct 2>/dev/null || true time dd if=/mnt/foo of=/dev/null bs=1M count=1024 umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } # Small filesystem tests currently disabled - TODO item: d_test_small_fs() { set_watchdog 60 run_quiet "" bcachefs format -f \ --errors=panic \ --bucket_size=4k \ --fs_size=512k \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt df -h /mnt dd if=/dev/zero of=/mnt/foo bs=4k oflag=direct 2>/dev/null || true df -h /mnt umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } d_test_small_torture() { run_copygc_torture --bucket_size=4k --fs_size=32M } d_test_small_fsck() { set_watchdog 60 run_quiet "" bcachefs format -f \ --errors=panic \ --fs_size=1M \ ${ktest_scratch_dev[0]} for i in {1..100}; do bcachefs fsck ${ktest_scratch_dev[0]} done } test_gc() { set_watchdog 60 run_quiet "" bcachefs format -f \ --errors=panic \ --compression=lz4 \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt antagonist_trigger_gc & run_fio_randrw umount /mnt mount -t bcachefs ${ktest_scratch_dev[0]} /mnt umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_attr_inherit() { set_watchdog 60 run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt mkdir /mnt/foo mkdir /mnt/bar setfattr -n bcachefs.compression -v lz4 /mnt/foo setfattr -n bcachefs.compression -v gzip /mnt/bar touch /mnt/foo/baz getfattr -R -d -m - /mnt mv /mnt/foo/baz /mnt/bar/baz getfattr -R -d -m - /mnt setfattr -n bcachefs.compression -v lz4 /mnt/bar/baz getfattr -R -d -m - /mnt/bar/baz setfattr -x bcachefs.compression /mnt/bar/baz getfattr -R -d -m - /mnt/bar/baz umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_setattr() { set_watchdog 60 run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt mkdir /mnt/foo touch /mnt/foo/bar bcachefs set-file-option --compression lz4 /mnt/foo bcachefs set-file-option --foreground_target= /mnt/foo getfattr -R -d -m - /mnt umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_mount_twice() { set_watchdog 60 mkdir -p /mnt/1 /mnt/2 #run_quiet "" bcachefs format -f ${ktest_scratch_dev[0]} mkfs.ext2 ${ktest_scratch_dev[0]} mount -t ext2 ${ktest_scratch_dev[0]} /mnt/1 mount -t ext2 ${ktest_scratch_dev[0]} /mnt/2 umount /mnt/1 umount /mnt/2 } test_dump() { set_watchdog 60 run_quiet "" bcachefs format -f ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt touch /mnt/a touch /mnt/b umount /mnt bcachefs dump -o /tmp/sdb.qcow2 ${ktest_scratch_dev[0]} } test_kill_btree_node() { set_watchdog 240 run_quiet "" bcachefs format -f --errors=panic ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt cp -a /usr /mnt umount /mnt # Doesn't yet work with the alloc btree: for btree in extents backpointers freespace; do echo "Killing a btree node in btree $btree " local index=1 [[ $btree = freespace ]] && index=0 bcachefs kill_btree_node -n$btree:0:$index ${ktest_scratch_dev[0]} echo "Running fsck" # How to assert exit status equals something specific with -o errexit? mount -t bcachefs -o fsck,fix_errors,verbose ${ktest_scratch_dev[0]} /mnt umount /mnt #bcachefs fsck -y ${ktest_scratch_dev[0]} || true echo echo "Running fsck again; should be clean" bcachefs fsck -ny ${ktest_scratch_dev[0]} done bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_kill_btree_root_autofix() { set_watchdog 240 run_quiet "" bcachefs format -f --btree_node_size=64k ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt cp -rL /usr/bin /mnt sync cat /sys/kernel/debug/bcachefs/*/btrees/extents/keys > /root/extents_before umount /mnt bcachefs list -m nodes ${ktest_scratch_dev[0]} > /root/nodes_before bcachefs kill_btree_node -nextents:1 ${ktest_scratch_dev[0]} echo "Running fsck" # How to assert exit status equals something specific with -o errexit? mount -t bcachefs ${ktest_scratch_dev[0]} /mnt cat /sys/kernel/debug/bcachefs/*/btrees/extents/keys > /root/extents_after umount /mnt bcachefs list -m nodes ${ktest_scratch_dev[0]} > /root/nodes_after #bcachefs fsck -y ${ktest_scratch_dev[0]} || true echo echo "Running fsck again; should be clean" bcachefs fsck -yk ${ktest_scratch_dev[0]} || true mount -t bcachefs -o fsck,fix_errors,verbose ${ktest_scratch_dev[0]} /mnt diff -rq /usr/bin /mnt/bin umount /mnt bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_kill_btree_root() { set_watchdog 240 run_quiet "" bcachefs format -f --btree_node_size=64k ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt cp -rL /usr/bin /mnt sync cat /sys/kernel/debug/bcachefs/*/btrees/extents/keys > /root/extents_before umount /mnt bcachefs list -m nodes ${ktest_scratch_dev[0]} > /root/nodes_before bcachefs kill_btree_node -nextents:1 -nsnapshots -nsnapshot_trees -nsubvolumes ${ktest_scratch_dev[0]} echo "Running fsck" # How to assert exit status equals something specific with -o errexit? mount -t bcachefs -o fsck,fix_errors ${ktest_scratch_dev[0]} /mnt cat /sys/kernel/debug/bcachefs/*/btrees/extents/keys > /root/extents_after umount /mnt bcachefs list -m nodes ${ktest_scratch_dev[0]} > /root/nodes_after #bcachefs fsck -y ${ktest_scratch_dev[0]} || true echo echo "Running fsck again; should be clean" bcachefs fsck -yk ${ktest_scratch_dev[0]} || true mount -t bcachefs -o fsck,fix_errors,verbose ${ktest_scratch_dev[0]} /mnt diff -rq /usr/bin /mnt/bin umount /mnt bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_multimount() { set_watchdog 10 bcachefs format -f ${ktest_scratch_dev[0]} mkdir -p /mnt/1 /mnt/2 mount -t bcachefs ${ktest_scratch_dev[0]} /mnt/1 mount -t bcachefs ${ktest_scratch_dev[0]} /mnt/2 umount /mnt/1 umount /mnt/2 bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_kernel_fsck() { set_watchdog 10 bcachefs format -f ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt touch /mnt/foo mkdir /mnt/bar umount /mnt bcachefs fsck -nyvk ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } test_online_fsck() { set_watchdog 30 bcachefs format -f ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt ( echo foo rm /mnt/foo sleep 10 echo bar ) > /mnt/foo & bcachefs fsck -yk ${ktest_scratch_dev[0]} wait umount /mnt bcachefs fsck -nyvk ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } d_test_nocow_fragmented() { set_watchdog 60 run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt run_fio_randrw echo 1 > /sys/fs/bcachefs/*/options/nocow dd if=/dev/zero of=/mnt/fiotest bs=1M oflag=direct umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} bcachefs_test_end_checks ${ktest_scratch_dev[0]} } d_test_nocow_fragmented2() { modprobe brd rd_size=536870912 rd_nr=7 bcachefs format -f --nocow \ --foreground_target=/dev/ram4 \ --promote_target=/dev/ram5 \ /dev/ram1 /dev/ram2 /dev/ram5 /dev/ram0 \ /dev/ram4 /dev/ram6 /dev/ram3 mount -t bcachefs /dev/ram1:/dev/ram2:/dev/ram5:/dev/ram0:/dev/ram4:/dev/ram6:/dev/ram3 /mnt fio --group_reporting \ --ioengine=io_uring \ --directory=/mnt --size=16m \ --time_based --runtime=60s \ --iodepth=256 --verify_async=8 \ --bs=4k-64k --norandommap \ --random_distribution=zipf:0.5 --numjobs=16 --rw=randrw \ --name=A --direct=1 --name=B --direct=0 >/dev/null & sleep 10 bcachefs device offline /dev/ram5 wait umount /mnt } test_recover_super() { set_watchdog 60 run_quiet "" bcachefs format -f \ --errors=panic \ ${ktest_scratch_dev[0]} bcachefs show-super -l ${ktest_scratch_dev[0]} mount -t bcachefs ${ktest_scratch_dev[0]} /mnt cp -rx /usr /mnt/usr umount /mnt echo "Wiping super" dd if=/dev/zero of=${ktest_scratch_dev[0]} bs=1M count=1 oflag=direct echo "Attempting mount, should fail" ! mount -t bcachefs ${ktest_scratch_dev[0]} /mnt echo "Recovering superblock" bcachefs recover-super -y ${ktest_scratch_dev[0]} echo "Attempting mount, should succeed" mount -t bcachefs -o fsck ${ktest_scratch_dev[0]} /mnt umount /mnt check_counters ${ktest_scratch_dev[0]} } # Check that we can mount multiple single device filesystems with the same UUID test_single_device() { run_quiet "" bcachefs format -f --no_initialize ${ktest_scratch_dev[0]} dd if=${ktest_scratch_dev[0]} of=${ktest_scratch_dev[1]} bs=1M count=8 oflag=direct mkdir -p /mnt2 mount ${ktest_scratch_dev[0]} /mnt mount ${ktest_scratch_dev[1]} /mnt2 umount /mnt2 umount /mnt } require-kernel-config OVERLAY_FS test_casefold_overlayfs() { run_quiet "" bcachefs format -f ${ktest_scratch_dev[0]} mount ${ktest_scratch_dev[0]} /mnt mkdir -p /mnt/dir/casefold bcachefs set-file-option --casefold /mnt/dir/casefold echo foo > /mnt/dir/casefold/foo cat /mnt/dir/casefold/FOO mkdir /mnt/lower mkdir /mnt/upper mkdir /mnt/work mkdir /mnt/merged echo "Testing an overlayfs on a casefold fs with non-casefolded dirs" mount -t overlay -o lowerdir=/mnt/lower,upperdir=/mnt/upper,workdir=/mnt/work overlay /mnt/merged umount /mnt/merged echo "Test using casefolded dir - should fail" ! mount -t overlay -o lowerdir=/mnt/casefold,upperdir=/mnt/dir/casefold,workdir=/mnt/work overlay /mnt/merged echo "Test using a dir with a casefold subdir - should mount" mount -t overlay -o lowerdir=/mnt/dir,upperdir=/mnt/upper,workdir=/mnt/work overlay /mnt/merged ! ls /mnt/merged/dir/casefold umount /mnt/merged umount /mnt bcachefs fsck -ny ${ktest_scratch_dev[0]} } test_image_create() { local IMAGE_FILE=/root/usr.image check_image() { echo "--- FSCK IMAGE ---" echo bcachefs fsck -ny $IMAGE_FILE ls -l $IMAGE_FILE echo "--- MOUNT CHECK IMAGE ---" echo mount $IMAGE_FILE /mnt verify_trees_equal /mnt $1 umount /mnt } #run_quiet "" bcachefs format -f ${ktest_scratch_dev[0]} #mount -t bcachefs ${ktest_scratch_dev[0]} /mnt rm -f $IMAGE_FILE echo "--- CREATE IMAGE ---" echo #bcachefs image create --compression=zstd --source=/usr $IMAGE_FILE bcachefs image create --source=/usr $IMAGE_FILE check_image /usr echo "--- UPDATE IMAGE /usr ---" echo bcachefs image update --source=/usr $IMAGE_FILE check_image /usr echo "--- UPDATE IMAGE /usr/bin ---" echo bcachefs image update --source=/usr/bin $IMAGE_FILE check_image /usr/bin } main "$@"