]> www.infradead.org Git - mtd-utils.git/commitdiff
tests: ubifs_tools: fsck_tests: Add random_corrupt+fsck test
authorZhihao Cheng <chengzhihao1@huawei.com>
Mon, 11 Nov 2024 09:08:24 +0000 (17:08 +0800)
committerDavid Oberhollenzer <david.oberhollenzer@sigma-star.at>
Mon, 11 Nov 2024 09:32:46 +0000 (10:32 +0100)
Inject random corruption on UBIFS image by writting random data on
kinds of mtd devices (eg. nand, nor), check the consistency of UBIFS
after fsck.
This testcase simulates random bad UBIFS image caused by hardware
exceptions(eg. ecc uncorrectable, unwritten), and makes sure that
fsck.ubifs could make UBIFS be consistent after repairing UBIFS
image.

Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
.gitignore
configure.ac
tests/ubifs_tools-tests/Makemodule.am
tests/ubifs_tools-tests/fsck_tests/random_corrupted_fsck.sh.in [new file with mode: 0755]

index 1d150f7ab8715bd1c4617586b335615c9d57bc33..203f01f08e82cca4e062a8f07309318f86f211e5 100644 (file)
@@ -119,6 +119,7 @@ tests/ubifs_tools-tests/fsck_tests/cycle_mount_fsck_check.sh
 tests/ubifs_tools-tests/fsck_tests/powercut_fsck_mount.sh
 tests/ubifs_tools-tests/fsck_tests/cycle_corrupted_fsck_fault_inject.sh
 tests/ubifs_tools-tests/fsck_tests/cycle_powercut_mount_fsck.sh
+tests/ubifs_tools-tests/fsck_tests/random_corrupted_fsck.sh
 
 #
 # Files generated by autotools
index 7b9294595a7d8f90dce23db85c402cd0ee51d67c..1b2591ba823d23022c6b47e4eac3b5ba2a7f468b 100644 (file)
@@ -298,7 +298,8 @@ AC_CONFIG_FILES([tests/fs-tests/fs_help_all.sh
        tests/ubifs_tools-tests/fsck_tests/cycle_mount_fsck_check.sh
        tests/ubifs_tools-tests/fsck_tests/powercut_fsck_mount.sh
        tests/ubifs_tools-tests/fsck_tests/cycle_corrupted_fsck_fault_inject.sh
-       tests/ubifs_tools-tests/fsck_tests/cycle_powercut_mount_fsck.sh])
+       tests/ubifs_tools-tests/fsck_tests/cycle_powercut_mount_fsck.sh
+       tests/ubifs_tools-tests/fsck_tests/random_corrupted_fsck.sh])
 
 AC_OUTPUT([Makefile])
 
index 2c190e2b2fcb67a941c5171d354fc701c0ded122..9881ebbe5a4efdd5e726f7d343ab3bc9dce7116b 100644 (file)
@@ -4,4 +4,5 @@ test_SCRIPTS += \
        tests/ubifs_tools-tests/fsck_tests/cycle_mount_fsck_check.sh \
        tests/ubifs_tools-tests/fsck_tests/powercut_fsck_mount.sh \
        tests/ubifs_tools-tests/fsck_tests/cycle_corrupted_fsck_fault_inject.sh \
-       tests/ubifs_tools-tests/fsck_tests/cycle_powercut_mount_fsck.sh
+       tests/ubifs_tools-tests/fsck_tests/cycle_powercut_mount_fsck.sh \
+       tests/ubifs_tools-tests/fsck_tests/random_corrupted_fsck.sh
diff --git a/tests/ubifs_tools-tests/fsck_tests/random_corrupted_fsck.sh.in b/tests/ubifs_tools-tests/fsck_tests/random_corrupted_fsck.sh.in
new file mode 100755 (executable)
index 0000000..64760c9
--- /dev/null
@@ -0,0 +1,206 @@
+#!/bin/sh
+# Copyright (c), 2024, Huawei Technologies Co, Ltd.
+# Author: Zhihao Cheng <chengzhihao1@huawei.com>
+#
+# Test Description:
+# For many kinds of flash, do following things
+#  1. mount UBIFS
+#  2. fsstress && unmount
+#  3. inject corruption into UBIFS image randomly
+#  3. fsck UBIFS
+#  4. check UBIFS mounting result
+# Running time: 1h
+
+TESTBINDIR=@TESTBINDIR@
+source $TESTBINDIR/common.sh
+
+function run_test()
+{
+       local simulator="$1";
+       local size="$2";
+       local peb_size="$3";
+       local page_size="$4";
+       local encryption=$5;
+
+       echo "======================================================================"
+       printf "%s" "$simulator: ${size}MiB PEB size ${peb_size}KiB"
+       if [ "$simulator" = "nandsim" ]; then
+               printf " %s" "page size ${page_size}Bytes"
+       fi
+       printf " $encryption\n"
+
+       if [ "$simulator" = "nandsim" ]; then
+               $TESTBINDIR/load_nandsim.sh "$size" "$peb_size" "$page_size" || echo "cannot load nandsim";
+               mtdnum="$(find_mtd_device "$nandsim_patt")"
+       elif [ "$simulator" = "mtdram" ]; then
+               load_mtdram "$size" "$peb_size" || echo "cannot load mtdram"
+               mtdnum="$(find_mtd_device "$mtdram_patt")"
+       else
+               fatal "$simulator is not supported"
+       fi
+
+       flash_eraseall /dev/mtd$mtdnum
+       modprobe ubi mtd="$mtdnum,$page_size" || fatal "modprobe ubi fail"
+       ubimkvol -N vol_test -m -n 0 /dev/ubi$UBI_NUM || fatal "mkvol fail"
+       modprobe ubifs || fatal "modprobe ubifs fail"
+       mount_ubifs $DEV $MNT || fatal "mount ubifs fail"
+       if [[ "$encryption" == "encrypted" ]]; then
+               encryption_gen_key
+               encryption_set_key $MNT
+       fi
+
+       fsstress -d $MNT -l0 -p4 -n10000 &
+
+       while true;
+       do
+               per=`df -Th | grep ubifs | awk '{print $6}'`;
+               if [[ ${per%?} -gt 95 ]]; then
+                       # Used > 95%
+                       break;
+               fi
+       done
+
+       ps -e | grep -w fsstress > /dev/null 2>&1
+       while [ $? -eq 0 ]
+       do
+               killall -9 fsstress > /dev/null 2>&1
+               sleep 1
+               ps -e | grep -w fsstress > /dev/null 2>&1
+       done
+
+       while true
+       do
+               res=`mount | grep "$MNT"`
+               if [[ "$res" == "" ]]
+               then
+                       break;
+               fi
+               umount $MNT
+               sleep 0.1
+       done
+
+       # injection
+       times=$((RANDOM % 10))
+       let times=$times+10
+       i=0
+       tot_peb=`cat /sys/class/ubi/ubi$UBI_NUM/total_eraseblocks`;
+
+       modprobe -r ubifs
+       modprobe -r ubi # Stop wear-leveling & erasing worker
+       while [[ $i -lt $times ]]
+       do
+               let i=$i+1;
+               peb=$((RANDOM % $tot_peb));
+               pg=`expr $peb_size \* 1024`;
+               peb_off=`expr $pg \* $peb`
+               pages=`expr $pg / $page_size`;
+               pg=`expr $pages - 2`;
+               pg=$((RANDOM % $pg));
+               pg_off=`expr $pg + 2`;
+               pg_start=`expr $pages \* $peb`;
+               pg=`expr $pg_start + $pg_off`;
+               vid_pg=`expr $pg_start + 1`;
+               dd if=/dev/mtd$mtdnum of=$TMP_FILE bs=$page_size skip=$vid_pg count=1 2>/dev/null;
+               content=`cat $TMP_FILE | grep UBI!`; # vid header magic
+               if [[ "$content" == "" ]]; then
+                       # Skip free PEB, otherwise data could be overwritten in UBIFS
+                       continue;
+               fi
+               if [[ $((RANDOM % 2)) == 0 ]]; then
+                       # Corrupts 1 page
+                       dd if=/dev/urandom of=/dev/mtd$mtdnum bs=$page_size seek=$pg count=1;
+               else
+                       # Erase 1 LEB, TNC points to an unmapped area
+                       flash_erase /dev/mtd$mtdnum $peb_off 1
+               fi
+       done
+       rm -f $TMP_FILE 2>/dev/null
+       sync
+
+       skip=0
+       modprobe ubi mtd="$mtdnum,$page_size"
+       ret=$?
+       if [[ $ret != 0 ]]
+       then
+               skip=1
+               echo "UBI layout volume is corrupted, skip"
+       fi
+
+       if [[ $skip == 0 ]]; then
+               modprobe ubifs || fatal "modprobe ubifs2 fail"
+               dmesg -c > /dev/null
+               fsck.ubifs -yb $DEV 2>&1 > $LOG_FILE
+               res=$?
+               cat $LOG_FILE
+               let "ret=$res&~$FSCK_NONDESTRUCT"
+               if [[ $ret != $FSCK_OK ]]
+               then
+                       # Skip superblock error
+                       log=`cat $LOG_FILE | grep "bad node at LEB 0:"`
+                       if [[ "$log" != "" ]]
+                       then
+                               skip=1
+                               echo "SB is corrupted, skip fsck & mounting"
+                       else
+                               fatal "fsck fail $res"
+                       fi
+               fi
+
+               if [[ $skip == 0 ]]; then
+                       enable_chkfs
+
+                       mount_ubifs $DEV $MNT "noauthentication" "noatime"
+                       res=$?
+                       if [[ $res != 0 ]]
+                       then
+                               fatal "mount fail $res"
+                       fi
+
+                       if [[ "$encryption" == "encrypted" ]]; then
+                               # Ignore the encrypting error, root dir could be
+                               # corrupted, the new root dir cannot be
+                               # encrypted because it is not empty.
+                               encryption_set_key $MNT 1
+                       fi
+
+                       du -sh $MNT > /dev/null  # Make sure all files are accessible
+                       ret=$?
+                       if [[ $ret != 0 ]]; then
+                               fatal "Cannot access all files"
+                       fi
+                       # check_err_msg is not suggested in this testcase, because
+                       # ubi_io_read(triggered by wear_leveling_worker -> ubi_eba_copy_leb)
+                       # could print stack if ecc uncorrectable errors are detected.
+
+                       umount $MNT
+                       res=$?
+                       if [[ $res != 0 ]]
+                       then
+                               fatal "unmount fail $res"
+                       fi
+               fi
+               modprobe -r ubifs
+               modprobe -r ubi
+       fi
+       modprobe -r $simulator
+
+       echo "----------------------------------------------------------------------"
+}
+
+check_fsstress
+start_t=$(date +%s)
+echo "Do random_corrruption+fsck+mount test in kinds of flashes"
+for simulator in "mtdram" "nandsim"; do
+       for encryption in "encrypted" "noencrypted"; do
+               run_test "$simulator" "16" "16" "512" $encryption
+               run_test "$simulator" "64" "16" "512" $encryption
+               run_test "$simulator" "128" "64" "2048" $encryption
+               run_test "$simulator" "256" "128" "2048" $encryption
+               run_test "$simulator" "512" "128" "2048" $encryption
+               run_test "$simulator" "1024" "512" "2048" $encryption
+       done
+done
+end_t=$(date +%s)
+time_cost=$(( end_t - start_t ))
+echo "Success, cost $time_cost seconds"
+exit 0