aboutsummaryrefslogtreecommitdiff
path: root/tests/ubifs_tools-tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ubifs_tools-tests')
-rw-r--r--tests/ubifs_tools-tests/Makemodule.am66
-rw-r--r--tests/ubifs_tools-tests/README.txt303
-rwxr-xr-xtests/ubifs_tools-tests/fsck_tests/authentication_refuse.sh.in66
-rwxr-xr-xtests/ubifs_tools-tests/fsck_tests/cycle_corrupted_fsck_fault_inject.sh.in225
-rwxr-xr-xtests/ubifs_tools-tests/fsck_tests/cycle_mount_fsck_check.sh.in154
-rwxr-xr-xtests/ubifs_tools-tests/fsck_tests/cycle_powercut_mount_fsck.sh.in148
-rwxr-xr-xtests/ubifs_tools-tests/fsck_tests/fsck_bad_image.sh.in355
-rwxr-xr-xtests/ubifs_tools-tests/fsck_tests/powercut_fsck_mount.sh.in148
-rwxr-xr-xtests/ubifs_tools-tests/fsck_tests/random_corrupted_fsck.sh.in206
-rw-r--r--tests/ubifs_tools-tests/images/corrupted_data_leb.gzbin0 -> 9536 bytes
-rw-r--r--tests/ubifs_tools-tests/images/corrupted_idx_leb.gzbin0 -> 5082 bytes
-rw-r--r--tests/ubifs_tools-tests/images/dentry_key.gzbin0 -> 5088 bytes
-rw-r--r--tests/ubifs_tools-tests/images/dentry_nlen.gzbin0 -> 5113 bytes
-rw-r--r--tests/ubifs_tools-tests/images/dentry_type.gzbin0 -> 5115 bytes
-rw-r--r--tests/ubifs_tools-tests/images/dir_lost.gzbin0 -> 5088 bytes
-rw-r--r--tests/ubifs_tools-tests/images/dir_lost_duplicated.gzbin0 -> 5347 bytes
-rw-r--r--tests/ubifs_tools-tests/images/dir_lost_not_recover.gzbin0 -> 5396 bytes
-rw-r--r--tests/ubifs_tools-tests/images/dir_many_dentry.gzbin0 -> 5114 bytes
-rw-r--r--tests/ubifs_tools-tests/images/empty_tnc.gzbin0 -> 4954 bytes
-rw-r--r--tests/ubifs_tools-tests/images/good.gzbin0 -> 4960 bytes
-rw-r--r--tests/ubifs_tools-tests/images/index_size.gzbin0 -> 5070 bytes
-rw-r--r--tests/ubifs_tools-tests/images/inode_data.gzbin0 -> 5015 bytes
-rw-r--r--tests/ubifs_tools-tests/images/inode_mode.gzbin0 -> 5109 bytes
-rw-r--r--tests/ubifs_tools-tests/images/inode_nlink.gzbin0 -> 5110 bytes
-rw-r--r--tests/ubifs_tools-tests/images/inode_size.gzbin0 -> 5113 bytes
-rw-r--r--tests/ubifs_tools-tests/images/inode_xcnt.gzbin0 -> 5115 bytes
-rw-r--r--tests/ubifs_tools-tests/images/journal_bud.gzbin0 -> 5015 bytes
-rw-r--r--tests/ubifs_tools-tests/images/journal_log.gzbin0 -> 4927 bytes
-rw-r--r--tests/ubifs_tools-tests/images/lpt_dirty.gzbin0 -> 5056 bytes
-rw-r--r--tests/ubifs_tools-tests/images/lpt_flags.gzbin0 -> 5060 bytes
-rw-r--r--tests/ubifs_tools-tests/images/lpt_free.gzbin0 -> 5046 bytes
-rw-r--r--tests/ubifs_tools-tests/images/lpt_pos.gzbin0 -> 5070 bytes
-rw-r--r--tests/ubifs_tools-tests/images/ltab_dirty.gzbin0 -> 5104 bytes
-rw-r--r--tests/ubifs_tools-tests/images/ltab_free.gzbin0 -> 5072 bytes
-rw-r--r--tests/ubifs_tools-tests/images/master_highest_inum.gzbin0 -> 4813 bytes
-rw-r--r--tests/ubifs_tools-tests/images/master_lpt.gzbin0 -> 4808 bytes
-rw-r--r--tests/ubifs_tools-tests/images/master_tnc.gzbin0 -> 4805 bytes
-rw-r--r--tests/ubifs_tools-tests/images/master_total_dead.gzbin0 -> 4817 bytes
-rw-r--r--tests/ubifs_tools-tests/images/master_total_dirty.gzbin0 -> 4814 bytes
-rw-r--r--tests/ubifs_tools-tests/images/master_total_free.gzbin0 -> 4813 bytes
-rw-r--r--tests/ubifs_tools-tests/images/orphan_node.gzbin0 -> 5379 bytes
-rw-r--r--tests/ubifs_tools-tests/images/root_dir.gzbin0 -> 5058 bytes
-rw-r--r--tests/ubifs_tools-tests/images/sb_fanout.gzbin0 -> 5031 bytes
-rw-r--r--tests/ubifs_tools-tests/images/sb_fmt_version.gzbin0 -> 5032 bytes
-rw-r--r--tests/ubifs_tools-tests/images/sb_leb_size.gzbin0 -> 5033 bytes
-rw-r--r--tests/ubifs_tools-tests/images/sb_log_lebs.gzbin0 -> 5031 bytes
-rw-r--r--tests/ubifs_tools-tests/images/sb_min_io_size.gzbin0 -> 5035 bytes
-rw-r--r--tests/ubifs_tools-tests/images/soft_link_data_len.gzbin0 -> 5112 bytes
-rw-r--r--tests/ubifs_tools-tests/images/soft_link_inode_mode.gzbin0 -> 5121 bytes
-rw-r--r--tests/ubifs_tools-tests/images/tnc_lv0_key.gzbin0 -> 5118 bytes
-rw-r--r--tests/ubifs_tools-tests/images/tnc_lv0_len.gzbin0 -> 5130 bytes
-rw-r--r--tests/ubifs_tools-tests/images/tnc_lv0_pos.gzbin0 -> 5118 bytes
-rw-r--r--tests/ubifs_tools-tests/images/tnc_noleaf_key.gzbin0 -> 5140 bytes
-rw-r--r--tests/ubifs_tools-tests/images/tnc_noleaf_len.gzbin0 -> 5145 bytes
-rw-r--r--tests/ubifs_tools-tests/images/tnc_noleaf_pos.gzbin0 -> 5125 bytes
-rw-r--r--tests/ubifs_tools-tests/images/xent_host.gzbin0 -> 5108 bytes
-rw-r--r--tests/ubifs_tools-tests/images/xentry_key.gzbin0 -> 5085 bytes
-rw-r--r--tests/ubifs_tools-tests/images/xentry_nlen.gzbin0 -> 5115 bytes
-rw-r--r--tests/ubifs_tools-tests/images/xentry_type.gzbin0 -> 5113 bytes
-rw-r--r--tests/ubifs_tools-tests/images/xinode_flags.gzbin0 -> 5112 bytes
-rw-r--r--tests/ubifs_tools-tests/images/xinode_key.gzbin0 -> 5110 bytes
-rw-r--r--tests/ubifs_tools-tests/images/xinode_mode.gzbin0 -> 5112 bytes
-rwxr-xr-xtests/ubifs_tools-tests/lib/common.sh.in359
-rwxr-xr-xtests/ubifs_tools-tests/mkfs_tests/build_fs_from_dir.sh.in174
-rwxr-xr-xtests/ubifs_tools-tests/ubifs_tools_run_all.sh.in65
65 files changed, 2269 insertions, 0 deletions
diff --git a/tests/ubifs_tools-tests/Makemodule.am b/tests/ubifs_tools-tests/Makemodule.am
new file mode 100644
index 0000000..1715757
--- /dev/null
+++ b/tests/ubifs_tools-tests/Makemodule.am
@@ -0,0 +1,66 @@
+test_SCRIPTS += \
+ tests/ubifs_tools-tests/lib/common.sh \
+ tests/ubifs_tools-tests/ubifs_tools_run_all.sh \
+ tests/ubifs_tools-tests/fsck_tests/authentication_refuse.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/random_corrupted_fsck.sh \
+ tests/ubifs_tools-tests/fsck_tests/fsck_bad_image.sh \
+ tests/ubifs_tools-tests/mkfs_tests/build_fs_from_dir.sh
+
+test_DATA += \
+ tests/ubifs_tools-tests/images/good.gz \
+ tests/ubifs_tools-tests/images/sb_fanout.gz \
+ tests/ubifs_tools-tests/images/sb_fmt_version.gz \
+ tests/ubifs_tools-tests/images/sb_leb_size.gz \
+ tests/ubifs_tools-tests/images/sb_log_lebs.gz \
+ tests/ubifs_tools-tests/images/sb_min_io_size.gz \
+ tests/ubifs_tools-tests/images/master_highest_inum.gz \
+ tests/ubifs_tools-tests/images/master_lpt.gz \
+ tests/ubifs_tools-tests/images/master_tnc.gz \
+ tests/ubifs_tools-tests/images/master_total_dead.gz \
+ tests/ubifs_tools-tests/images/master_total_dirty.gz \
+ tests/ubifs_tools-tests/images/master_total_free.gz \
+ tests/ubifs_tools-tests/images/journal_log.gz \
+ tests/ubifs_tools-tests/images/journal_bud.gz \
+ tests/ubifs_tools-tests/images/orphan_node.gz \
+ tests/ubifs_tools-tests/images/lpt_dirty.gz \
+ tests/ubifs_tools-tests/images/lpt_flags.gz \
+ tests/ubifs_tools-tests/images/lpt_free.gz \
+ tests/ubifs_tools-tests/images/lpt_pos.gz \
+ tests/ubifs_tools-tests/images/ltab_dirty.gz \
+ tests/ubifs_tools-tests/images/ltab_free.gz \
+ tests/ubifs_tools-tests/images/index_size.gz \
+ tests/ubifs_tools-tests/images/tnc_lv0_key.gz \
+ tests/ubifs_tools-tests/images/tnc_lv0_len.gz \
+ tests/ubifs_tools-tests/images/tnc_lv0_pos.gz \
+ tests/ubifs_tools-tests/images/tnc_noleaf_key.gz \
+ tests/ubifs_tools-tests/images/tnc_noleaf_len.gz \
+ tests/ubifs_tools-tests/images/tnc_noleaf_pos.gz \
+ tests/ubifs_tools-tests/images/corrupted_data_leb.gz \
+ tests/ubifs_tools-tests/images/corrupted_idx_leb.gz \
+ tests/ubifs_tools-tests/images/inode_data.gz \
+ tests/ubifs_tools-tests/images/inode_mode.gz \
+ tests/ubifs_tools-tests/images/inode_nlink.gz \
+ tests/ubifs_tools-tests/images/inode_size.gz \
+ tests/ubifs_tools-tests/images/inode_xcnt.gz \
+ tests/ubifs_tools-tests/images/soft_link_inode_mode.gz \
+ tests/ubifs_tools-tests/images/soft_link_data_len.gz \
+ tests/ubifs_tools-tests/images/dentry_key.gz \
+ tests/ubifs_tools-tests/images/dentry_nlen.gz \
+ tests/ubifs_tools-tests/images/dentry_type.gz \
+ tests/ubifs_tools-tests/images/xinode_flags.gz \
+ tests/ubifs_tools-tests/images/xinode_key.gz \
+ tests/ubifs_tools-tests/images/xinode_mode.gz \
+ tests/ubifs_tools-tests/images/xentry_key.gz \
+ tests/ubifs_tools-tests/images/xentry_nlen.gz \
+ tests/ubifs_tools-tests/images/xentry_type.gz \
+ tests/ubifs_tools-tests/images/xent_host.gz \
+ tests/ubifs_tools-tests/images/dir_many_dentry.gz \
+ tests/ubifs_tools-tests/images/dir_lost.gz \
+ tests/ubifs_tools-tests/images/dir_lost_duplicated.gz \
+ tests/ubifs_tools-tests/images/dir_lost_not_recover.gz \
+ tests/ubifs_tools-tests/images/root_dir.gz \
+ tests/ubifs_tools-tests/images/empty_tnc.gz
diff --git a/tests/ubifs_tools-tests/README.txt b/tests/ubifs_tools-tests/README.txt
new file mode 100644
index 0000000..9e94c22
--- /dev/null
+++ b/tests/ubifs_tools-tests/README.txt
@@ -0,0 +1,303 @@
+
+ ubifs_tools tests
+ ==================
+
+ There are seven testcases for fsck.ubifs on encryption/non-encryption
+ situations:
+ 1) authentication_refuse: Currently authenticated UBIFS image is not
+ supported for fsck.ubifs, check whether fsck.ubifs can refuse the
+ authenticated UBIFS image.
+ 2) random_corrupted_fsck: Inject random corruption on UBIFS image
+ by writing random data on kinds of mtd devices (eg. nand, nor),
+ check the consistency of UBIFS after fsck.
+ This testcase simulate 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.
+ 3) cycle_corrupted_fsck_fault_inject: Inject memory/io fault while
+ doing fsck for corrupted UBIFS images.
+ This testcase mainly checks whether fsck.ubifs has problems (eg.
+ UAF, null-ptr-def, etc.) in random error paths. Besides, it
+ provides a similar way to simulate powercut during fsck, and
+ checks whether the fsck.ubifs can fix an UBIFS image after many
+ rounds interrupted by kinds of errors.
+ 4) cycle_powercut_mount_fsck: Inject powercut while doing fsstress
+ on mounted UBIFS, check the consistency of UBIFS after fsck.
+ This testscase mainly makes sure that fsck.ubifs can make UBIFS
+ image be consistent in common stress cases and powercut cases.
+ 5) powercut_fsck_mount: Inject powercut while doing fsstress on
+ mounted UBIFS for kinds of flashes (eg. nand, nor).
+ This testcase mainly makes sure that fsck.ubifs can make UBIFS
+ image be consistent on different flashes (eg. nand, nor). Because
+ the min_io_size of nor flash is 1, the UBIFS image on nor flash
+ will be different from nand flash after doing powercut, so we need
+ make sure fsck.ubifs can handle these two types of flash.
+ 6) cycle_mount_fsck_check: Do fsstress and fsck ubifs image, make
+ sure all files(and their data) are not lost after fsck.
+ This testcase mainly checks whether fsck.ubifs could corrupt the
+ filesystem content in common case.
+ 7) fsck_bad_image: For kinds of inconsistent UBIFS images(which
+ can simulate corruptions caused by some potentional UBIFS bug), check
+ the result of fsck.
+ This testcase mainly checks whether the behavior is in expected after
+ repairing specific inconsistent UBIFS image. There is no debugfs tools
+ (for example: debugfs[ext4], xfs_db) for UBIFS, so no way to inject
+ precise corruption into UBIFS image, we have to prepare inconsistent
+ UBIFS images in advance like e2fsprogs[1] does. (Goto [2] to see how to
+ generate inconsistent UBIFS images).
+ Original UBIFS image content:
+ /
+ ├── corrupt_file (xattr - user.corrupt:123, 2K data)
+ ├── dir
+ │   ├── block_dev
+ │   ├── char_dev
+ │   ├── dir
+ │   └── file (content: '123')
+ ├── hardl_corrupt_file => corrupt_file
+ └── softl_corrupt_file -> corrupt_file
+ Here's a descriptons of the various test images:
+ =========================================================================
+ image | Description | expectancy
+ -------------------------------------------------------------------------
+ good | good image contains | fsck success, fs content is
+ | kinds of files. | not changed.
+ -------------------------------------------------------------------------
+ sb_fanout | invalid fanout in | fsck failed.
+ | superblock. |
+ -------------------------------------------------------------------------
+ sb_fmt_version | invalid fmt_version | fsck failed.
+ | in superblock. |
+ -------------------------------------------------------------------------
+ sb_leb_size | invalid leb_size in | fsck failed.
+ | superblock. |
+ -------------------------------------------------------------------------
+ sb_log_lebs | invalid log lebs in | fsck failed.
+ | superblock. |
+ -------------------------------------------------------------------------
+ sb_min_io_size | invalid min_io_size | fsck failed.
+ | in superblock. |
+ -------------------------------------------------------------------------
+ master_highest_inum | invalid highest_inum| fsck success, fs content is
+ | in master nodes. | not changed.
+ -------------------------------------------------------------------------
+ master_lpt | bad lpt pos in | fsck success, fs content is
+ | master nodes. | not changed.
+ -------------------------------------------------------------------------
+ master_tnc | bad tnc pos in | fsck success, fs content is
+ | master nodes. | not changed.
+ -------------------------------------------------------------------------
+ master_total_dead | bad total_dead in | fsck success, fs content is
+ | master nodes. | not changed.
+ -------------------------------------------------------------------------
+ master_total_dirty | bad total_dirty in | fsck success, fs content is
+ | master nodes. | not changed.
+ -------------------------------------------------------------------------
+ master_total_free | bad total_free in | fsck success, fs content is
+ | master nodes. | not changed.
+ -------------------------------------------------------------------------
+ journal_log | corrupted log area. | fsck success, fs content is
+ | | not changed.
+ -------------------------------------------------------------------------
+ journal_bud | corrupted bud area. | fsck success, file data is
+ | | lost.
+ -------------------------------------------------------------------------
+ orphan_node | bad orphan node. | fsck success, file is
+ | | deleted as expected.
+ -------------------------------------------------------------------------
+ lpt_dirty | bad dirty in pnode. | fsck success, fs content is
+ | | not changed.
+ -------------------------------------------------------------------------
+ lpt_flags | bad flags in pnode | fsck success, fs content is
+ | (eg. index). | not changed.
+ -------------------------------------------------------------------------
+ lpt_free | bad free in pnode. | fsck success, fs content is
+ | | not changed.
+ -------------------------------------------------------------------------
+ lpt_pos | bad pos in nnode. | fsck success, fs content is
+ | | not changed.
+ -------------------------------------------------------------------------
+ ltab_dirty | bad dirty in lprops | fsck success, fs content is
+ | table. | not changed.
+ -------------------------------------------------------------------------
+ ltab_free | bad free in lprops | fsck success, fs content is
+ | table. | not changed.
+ -------------------------------------------------------------------------
+ index_size | bad index size in | fsck success, fs content is
+ | master nodes. | not changed.
+ -------------------------------------------------------------------------
+ tnc_lv0_key | bad key in lv0 | fsck success, fs content is
+ | znode. | not changed.
+ -------------------------------------------------------------------------
+ tnc_lv0_len | bad len in lv0 | fsck success, fs content is
+ | znode. | not changed.
+ -------------------------------------------------------------------------
+ tnc_lv0_pos | bad pos in lv0 | fsck success, fs content is
+ | znode. | not changed.
+ -------------------------------------------------------------------------
+ tnc_noleaf_key | bad key in non-leaf | fsck success, fs content is
+ | znode. | not changed.
+ -------------------------------------------------------------------------
+ tnc_noleaf_len | bad len in non-leaf | fsck success, fs content is
+ | znode. | not changed.
+ -------------------------------------------------------------------------
+ tnc_noleaf_pos | bad pos in non-leaf | fsck success, fs content is
+ | znode. | not changed.
+ -------------------------------------------------------------------------
+ corrupted_data_leb | corrupted data leb. | fsck success, partial data of
+ | | file is lost.
+ -------------------------------------------------------------------------
+ corrupted_idx_leb | corrupted index leb.| fsck success, fs content is
+ | | not changed.
+ -------------------------------------------------------------------------
+ inode_data | bad data node. | fsck success, file content
+ | | is changed, other files are
+ | | not changed.
+ -------------------------------------------------------------------------
+ inode_mode | bad inode mode for | fsck success, file is
+ | file. | dropped, other files are not
+ | | changed.
+ -------------------------------------------------------------------------
+ inode_nlink | wrong nlink for | fsck success, nlink is
+ | file. | corrected, fs content is not
+ | | changed.
+ -------------------------------------------------------------------------
+ inode_size | wrong inode size | fsck success, inode size is
+ | for file. | corrected, fs content is not
+ | | changed.
+ -------------------------------------------------------------------------
+ inode_xcnt | wrong inode | fsck success, xattr_cnt is
+ | xattr_cnt for file. | corrected, fs content is not
+ | | changed.
+ -------------------------------------------------------------------------
+ soft_link_inode_mode| bad inode mode for | fsck success, soft link
+ | solf link file. | file is dropped, other files
+ | | are not changed.
+ -------------------------------------------------------------------------
+ soft_link_data_len | bad inode data_len | fsck success, soft link
+ | for solt link file. | file is dropped, other files
+ | | are not changed.
+ -------------------------------------------------------------------------
+ dentry_key | bad dentry key for | fsck success, dentry is
+ | file. | removed, other files are
+ | | not changed.
+ -------------------------------------------------------------------------
+ dentry_nlen | inconsistent nlen | fsck success, dentry is
+ | and name in dentry | removed, other files are
+ | for file. | not changed.
+ -------------------------------------------------------------------------
+ dentry_type | inconsistent type | fsck success, dentry is
+ | between dentry and | removed, other files are
+ | inode for file. | not changed.
+ -------------------------------------------------------------------------
+ xinode_flags | lost UBIFS_XATTR_FL | fsck success, xattr is
+ | in xattr inode | removed, other files are
+ | flags for file. | not changed.
+ -------------------------------------------------------------------------
+ xinode_key | bad xattr inode key | fsck success, xattr is
+ | for file. | removed, other files are
+ | | not changed.
+ -------------------------------------------------------------------------
+ xinode_mode | bad xattr inode | fsck success, xattr is
+ | mode for file. | removed, other files are
+ | | not changed.
+ -------------------------------------------------------------------------
+ xentry_key | bad xattr entry key | fsck success, xattr is
+ | for file. | removed, other files are
+ | | not changed.
+ -------------------------------------------------------------------------
+ xentry_nlen | inconsistent nlen | fsck success, xattr is
+ | and name in xattr | removed, other files are
+ | entry for file. | not changed.
+ -------------------------------------------------------------------------
+ xentry_type | inconsistent type | fsck success, xattr is
+ | between xattr entry | removed, other files are
+ | and xattr inode for | not changed.
+ | file. |
+ -------------------------------------------------------------------------
+ xent_host | the xattr's host | fsck success, file, hard
+ | is a xattr too, the | link and soft link are
+ | flag of corrupt_file| dropped, other files are
+ | inode is modified. | not changed.
+ -------------------------------------------------------------------------
+ dir_many_dentry | dir has too many | fsck success, hard link is
+ | dentries, the dentry| dropped, other files are not
+ | of hard link is | changed.
+ | modified. |
+ -------------------------------------------------------------------------
+ dir_lost | bad dentry for dir. | fsck success, the 'file' is
+ | | recovered under lost+found,
+ | | left files under dir are
+ | | removed, other files are not
+ | | changed.
+ -------------------------------------------------------------------------
+ dir_lost_duplicated | bad inode for dir, | fsck success, the 'file' is
+ | there is a file | recovered with INO_<inum>_1
+ | under lost+found, | under lost+found, left files
+ | which named with the| under dir are removed, other
+ | inum of the 'file'. | files are not changed.
+ -------------------------------------------------------------------------
+ dir_lost_not_recover| bad inode for dir, | fsck success, all files
+ | lost+found is a | under dir are removed,
+ | regular file and | other files are not changed.
+ | exists under root |
+ | dir. |
+ -------------------------------------------------------------------------
+ root_dir | bad '/'. | fsck success, create new
+ | | root dir('/'). All regular
+ | | files are reocovered under
+ | | lost+found, other files are
+ | | removed.
+ -------------------------------------------------------------------------
+ empty_tnc | all files have bad | fsck success, fs content
+ | inode. | becomes empty.
+ =========================================================================
+
+ There is one testcase for mkfs.ubifs on encryption/non-encryption
+ situations:
+ 1) build_fs_from_dir: Initialize UBIFS image from a given directory, then
+ check whether the fs content in mounted UBIFS is consistent with the
+ original directory. Both UBI volume and file are chosen as storage
+ mediums to test. This testcase mainly ensures that mkfs.ubifs can
+ format an UBIFS image as user expected.
+
+ Dependence
+ ----------
+ kernel configs:
+ CONFIG_MTD_NAND_NANDSIM=m
+ CONFIG_MTD_MTDRAM=m
+ CONFIG_MTD_UBI=m
+ CONFIG_UBIFS_FS=m
+ CONFIG_UBIFS_FS_XATTR=y
+ CONFIG_UBIFS_FS_AUTHENTICATION=y
+ CONFIG_FS_ENCRYPTION=y
+ CONFIG_FAILSLAB=y
+ CONFIG_FAIL_PAGE_ALLOC=y
+
+ tools:
+ fsstress [3][4]
+ keyctl [5]
+ fscryptctl [6]
+ setfattr/getfattr [7]
+
+ Running
+ -------
+
+ Please build and install mtd-utils first.
+ Run single case:
+ cd $INSTALL_DIR/libexec/mtd-utils
+ ./powercut_fsck_mount.sh
+ ./random_corrupted_fsck.sh
+ ./cycle_mount_fsck_check.sh
+ ./build_fs_from_dir.sh
+ Run all cases: sh $INSTALL_DIR/libexec/mtd-utils/ubifs_tools_run_all.sh
+
+ References
+ ----------
+
+ [1] https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git/tree/tests/README
+ [2] https://bugzilla.kernel.org/show_bug.cgi?id=218924
+ [3] https://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git/tree/ltp/fsstress.c
+ [4] https://github.com/linux-test-project/ltp/blob/master/testcases/kernel/fs/fsstress/fsstress.c
+ [5] https://github.com/torvalds/linux/blob/master/security/keys/keyctl.c
+ [6] https://github.com/google/fscryptctl
+ [7] https://github.com/philips/attr/tree/master
diff --git a/tests/ubifs_tools-tests/fsck_tests/authentication_refuse.sh.in b/tests/ubifs_tools-tests/fsck_tests/authentication_refuse.sh.in
new file mode 100755
index 0000000..268a7de
--- /dev/null
+++ b/tests/ubifs_tools-tests/fsck_tests/authentication_refuse.sh.in
@@ -0,0 +1,66 @@
+#!/bin/sh
+# Copyright (c), 2024, Huawei Technologies Co, Ltd.
+# Author: Zhihao Cheng <chengzhihao1@huawei.com>
+#
+# Test Description:
+# Refuse checking authenticated UBIFS image
+# Running time: 10s
+
+TESTBINDIR=@TESTBINDIR@
+source $TESTBINDIR/common.sh
+
+ID="0xec,0xa1,0x00,0x15" # 128M 128KB 2KB 512-sub-page
+
+function run_test()
+{
+ echo "Do authentication_refused test"
+
+ modprobe nandsim id_bytes=$ID
+ mtdnum="$(find_mtd_device "$nandsim_patt")"
+ flash_eraseall /dev/mtd$mtdnum
+
+ modprobe ubi mtd="$mtdnum,2048" || 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 "authentication" || fatal "mount ubifs failed"
+ fsstress -d $MNT/fsstress -l0 -p4 -n10000 &
+ sleep $((RANDOM % 5))
+
+ 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
+
+ fsck.ubifs -a $DEV # 'fsck.ubifs $DEV' is fine too.
+ res=$?
+ if [[ $res == $FSCK_OK ]]
+ then
+ fatal "fsck should not be success!"
+ fi
+
+ modprobe -r ubifs
+ modprobe -r ubi
+ modprobe -r nandsim
+}
+
+start_t=$(date +%s)
+run_test
+end_t=$(date +%s)
+time_cost=$(( end_t - start_t ))
+echo "Success, cost $time_cost seconds"
+exit 0
diff --git a/tests/ubifs_tools-tests/fsck_tests/cycle_corrupted_fsck_fault_inject.sh.in b/tests/ubifs_tools-tests/fsck_tests/cycle_corrupted_fsck_fault_inject.sh.in
new file mode 100755
index 0000000..2073fec
--- /dev/null
+++ b/tests/ubifs_tools-tests/fsck_tests/cycle_corrupted_fsck_fault_inject.sh.in
@@ -0,0 +1,225 @@
+#!/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 && inject kinds of errors(memory, io)
+# 4. check UBIFS mounting result
+# Running time: 15min
+
+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 &
+
+ sleep $((RANDOM % 20))
+
+ 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
+
+ # inject corruption
+ 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 LEB 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
+
+ round=0
+ while [[ $round -lt 50 ]];
+ do
+ let round=$round+1
+ inject_mem=0
+
+ fsck.ubifs -yb $DEV 2>&1 > $LOG_FILE &
+ pid=$!
+ if [[ $((RANDOM % 2)) == 0 ]]; then
+ inject_mem_err $pid
+ inject_mem=1
+ fi
+ inject_io_err
+ wait $pid
+ cat $LOG_FILE
+ if [[ $inject_mem == 1 ]]; then
+ cancel_mem_err
+ fi
+ cancel_io_err
+
+ # UBI could become ro-mode, reload it
+ modprobe -r ubifs
+ modprobe -r ubi
+ modprobe ubi mtd="$mtdnum,$page_size" || fatal "modprobe ubi2 fail"
+ modprobe ubifs || fatal "modprobe ubifs3 fail"
+ done
+
+ 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 corrruption+cycle_fsck_fault_injection 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" "256" "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
diff --git a/tests/ubifs_tools-tests/fsck_tests/cycle_mount_fsck_check.sh.in b/tests/ubifs_tools-tests/fsck_tests/cycle_mount_fsck_check.sh.in
new file mode 100755
index 0000000..c9972e2
--- /dev/null
+++ b/tests/ubifs_tools-tests/fsck_tests/cycle_mount_fsck_check.sh.in
@@ -0,0 +1,154 @@
+#!/bin/sh
+# Copyright (c), 2024, Huawei Technologies Co, Ltd.
+# Author: Zhihao Cheng <chengzhihao1@huawei.com>
+#
+# Test Description:
+# Do many cycles of mount/fsstress/umount/fsck/mount, check whether the
+# filesystem content before fsck and after fsck are consistent.
+# Running time: 10h
+
+TESTBINDIR=@TESTBINDIR@
+source $TESTBINDIR/common.sh
+
+ID="0xec,0xa1,0x00,0x15" # 128M 128KB 2KB 512-sub-page
+
+function run_test()
+{
+ encryption=$1
+ modprobe nandsim id_bytes=$ID
+ mtdnum="$(find_mtd_device "$nandsim_patt")"
+ flash_eraseall /dev/mtd$mtdnum
+
+ dmesg -c > /dev/null
+
+ modprobe ubi mtd="$mtdnum,2048" || fatal "modprobe ubi fail"
+ ubimkvol -N vol_test -m -n 0 /dev/ubi$UBI_NUM || fatal "mkvol fail"
+ modprobe ubifs || fatal "modprobe ubifs fail"
+
+ echo "Do cycle mount+umount+fsck+check_fs_content test ($encryption)"
+
+ if [[ "$encryption" == "encrypted" ]]; then
+ encryption_gen_key
+ fi
+
+ round=0
+ while [[ $round -lt 20 ]]
+ do
+ echo "---------------------- ROUND $round ----------------------"
+ let round=$round+1
+
+ mount_ubifs $DEV $MNT "noauthentication" "noatime" || fatal "mount ubifs fail"
+ if [[ "$encryption" == "encrypted" ]]; then
+ encryption_set_key $MNT
+ fi
+
+ per=`df -Th | grep ubifs | awk '{print $6}'`;
+ if [[ ${per%?} -gt 95 ]]; then
+ # Used > 95%
+ echo "Clean files"
+ rm -rf $MNT/*
+ check_err_msg
+ fi
+
+ fsstress -d $MNT -l0 -p4 -n10000 &
+
+ sleep $((RANDOM % 30))
+
+ 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
+
+ per=`df -Th | grep ubifs | awk '{print $6}'`;
+ if [[ ${per%?} -gt 95 ]]; then
+ dmesg -c > /dev/null # The ENOSPC error messages may exist
+ else
+ check_err_msg # Make sure new operations are okay after fsck
+ fi
+ sync
+
+ # Record filesystem information
+ rm -f $TMP_FILE 2>/dev/null
+ read_dir $MNT "md5sum"
+
+ while true
+ do
+ res=`mount | grep "$MNT"`
+ if [[ "$res" == "" ]]
+ then
+ break;
+ fi
+ umount $MNT
+ sleep 0.1
+ done
+
+ fsck.ubifs -a $DEV 2>&1 > $LOG_FILE
+ res=$?
+ cat $LOG_FILE
+ if [[ $res != $FSCK_OK ]]
+ then
+ # The lpt nodes could be parsed incorrectly because the lpt disk
+ # layout is too simple. See details in
+ # https://lore.kernel.org/linux-mtd/97ca7fe4-4ad4-edd1-e97a-1d540aeabe2d@huawei.com/
+ log=`cat $LOG_FILE | grep "dbg_check_ltab_lnum: invalid empty space in LEB"`
+ if [[ "$log" == "" ]]; then
+ fatal "fsck fail $res"
+ fi
+ if [[ $res != $FSCK_NONDESTRUCT ]]; then
+ fatal "fsck fail $res"
+ fi
+ fi
+
+ enable_chkfs
+
+ mount_ubifs $DEV $MNT "noauthentication" "noatime"
+ res=$?
+ if [[ $res != 0 ]]
+ then
+ fatal "mount fail $res"
+ fi
+
+ if [[ "$encryption" == "encrypted" ]]; then
+ encryption_set_key $MNT
+ fi
+
+ du -sh $MNT > /dev/null # Ensure that all files are accessible
+ ret=$?
+ if [[ $ret != 0 ]]; then
+ fatal "Cannot access all files"
+ fi
+ check_err_msg
+
+ # Check filesystem information
+ parse_dir "md5sum"
+ rm -f $TMP_FILE 2>/dev/null
+
+ umount $MNT
+ res=$?
+ if [[ $res != 0 ]]
+ then
+ fatal "unmount fail $res"
+ fi
+
+ check_err_msg
+
+ disable_chkfs
+ done
+
+ modprobe -r ubifs
+ modprobe -r ubi
+ modprobe -r nandsim
+}
+
+check_fsstress
+start_t=$(date +%s)
+for encryption in "encrypted" "noencrypted"; do
+ run_test $encryption
+done
+end_t=$(date +%s)
+time_cost=$(( end_t - start_t ))
+echo "Success, cost $time_cost seconds"
+exit 0
diff --git a/tests/ubifs_tools-tests/fsck_tests/cycle_powercut_mount_fsck.sh.in b/tests/ubifs_tools-tests/fsck_tests/cycle_powercut_mount_fsck.sh.in
new file mode 100755
index 0000000..6af1b54
--- /dev/null
+++ b/tests/ubifs_tools-tests/fsck_tests/cycle_powercut_mount_fsck.sh.in
@@ -0,0 +1,148 @@
+#!/bin/sh
+# Copyright (c), 2024, Huawei Technologies Co, Ltd.
+# Author: Zhihao Cheng <chengzhihao1@huawei.com>
+#
+# Test Description:
+# Do many cycles of mount/fsstress/powercut/umount/fsck/mount, check whether
+# mount is successful.
+# Running time: 9h
+
+TESTBINDIR=@TESTBINDIR@
+source $TESTBINDIR/common.sh
+
+ID="0x20,0xa7,0x00,0x26" # 4G 256KB 4KB 2KB-sub-page
+
+function run_test()
+{
+ local encryption=$1
+
+ echo "Do cycle mount+powercut+fsck+umount($encryption) test"
+ modprobe nandsim id_bytes=$ID
+ mtdnum="$(find_mtd_device "$nandsim_patt")"
+ flash_eraseall /dev/mtd$mtdnum
+
+ dmesg -c > /dev/null
+
+ modprobe ubi mtd="$mtdnum,4096" || fatal "modprobe ubi fail"
+ ubimkvol -N vol_test -m -n 0 /dev/ubi$UBI_NUM || fatal "mkvol fail"
+ modprobe ubifs || fatal "modprobe ubifs fail"
+
+ if [[ "$encryption" == "encrypted" ]]; then
+ encryption_gen_key
+ fi
+
+ round=0
+ while [[ $round -lt 60 ]]
+ do
+ echo "---------------------- ROUND $round ----------------------"
+ let round=$round+1
+
+ mount_ubifs $DEV $MNT || fatal "mount ubifs fail"
+ if [[ "$encryption" == "encrypted" ]]; then
+ encryption_set_key $MNT
+ fi
+
+ if [[ $(($round % 30)) == 0 ]]
+ then
+ echo "Clean files"
+ rm -rf $MNT/*
+ check_err_msg
+ fi
+
+ fsstress -d $MNT -l0 -p4 -n10000 &
+ sleep $((RANDOM % 30))
+
+ per=`df -Th | grep ubifs | awk '{print $6}'`;
+ if [[ ${per%?} -gt 95 ]]; then
+ dmesg -c > /dev/null # The ENOSPC error messages may exist
+ else
+ check_err_msg # Make sure new operations are okay after fsck
+ fi
+ powercut
+
+ 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
+
+ fsck.ubifs -a $DEV 2>&1 > $LOG_FILE
+ res=$?
+ cat $LOG_FILE
+ if [[ $res != $FSCK_OK ]]
+ then
+ # Powercut during layout_leb_in_gaps may change index
+ # LEBs without updating LPT.
+ idx_log=`cat $LOG_FILE | grep "Inconsistent properties" | grep "is_idx 1"`
+ # The lpt nodes could be parsed incorrectly because the lpt disk
+ # layout is too simple. See details in
+ # https://lore.kernel.org/linux-mtd/97ca7fe4-4ad4-edd1-e97a-1d540aeabe2d@huawei.com/
+ lpt_log=`cat $LOG_FILE | grep "dbg_check_ltab_lnum: invalid empty space in LEB"`
+ if [[ "$idx_log" == "" ]] && [[ "$lpt_log" == "" ]]; then
+ fatal "fsck fail $res"
+ fi
+ if [[ $res != $FSCK_NONDESTRUCT ]]; then
+ fatal "fsck fail $res"
+ fi
+ fi
+
+ dmesg -c > /dev/null # powercut could reproduce error messages
+
+ enable_chkfs
+
+ mount_ubifs $DEV $MNT "noauthentication" "noatime"
+ res=$?
+ if [[ $res != 0 ]]
+ then
+ fatal "mount fail $res"
+ fi
+
+ if [[ "$encryption" == "encrypted" ]]; then
+ encryption_set_key $MNT
+ 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
+
+ umount $MNT
+ res=$?
+ if [[ $res != 0 ]]
+ then
+ fatal "unmount fail $res"
+ fi
+
+ check_err_msg
+
+ disable_chkfs
+ done
+
+ modprobe -r ubifs
+ modprobe -r ubi
+ modprobe -r nandsim
+}
+
+check_fsstress
+start_t=$(date +%s)
+run_test "encrypted"
+run_test "noencrypted"
+end_t=$(date +%s)
+time_cost=$(( end_t - start_t ))
+echo "Success, cost $time_cost seconds"
+exit 0
diff --git a/tests/ubifs_tools-tests/fsck_tests/fsck_bad_image.sh.in b/tests/ubifs_tools-tests/fsck_tests/fsck_bad_image.sh.in
new file mode 100755
index 0000000..2ba9f78
--- /dev/null
+++ b/tests/ubifs_tools-tests/fsck_tests/fsck_bad_image.sh.in
@@ -0,0 +1,355 @@
+#!/bin/sh
+# Copyright (c), 2024, Huawei Technologies Co, Ltd.
+# Author: Zhihao Cheng <chengzhihao1@huawei.com>
+#
+# Test Description: Tests whether all inconsistent UBIFS images can be fixed
+# as expected.
+# Origin UBIFS image content:
+# /
+# ├── corrupt_file (xattr - user.corrupt:123, 2K data)
+# ├── dir
+# │   ├── block_dev
+# │   ├── char_dev
+# │   ├── dir
+# │   └── file (content: '123')
+# ├── hardl_corrupt_file => corrupt_file
+# └── softl_corrupt_file -> corrupt_file
+#
+# Running time: 2min
+
+TESTBINDIR=@TESTBINDIR@
+source $TESTBINDIR/common.sh
+
+CORRUPT_FILE=corrupt_file
+CORRUPT_FILE_INUM=INO_65
+XATTR_NAME="user.corrupt"
+XATTR_VAL=123
+CORRUPT_FILE_MD5=7d2f953e91033c743ab6a801d5ee6e15
+SOFT_LINK_FILE=softl_corrupt_file
+HARD_LINK_FILE=hardl_corrupt_file
+DIR=dir
+BLOCK_DEV=block_dev
+CHAR_DEV=char_dev
+FILE=file
+FILE_INUM=INO_72
+FILE_MD5=ba1f2511fc30423bdbb183fe33f3dd0f
+LOST_FOUND="lost+found"
+
+function fsck_image()
+{
+ local img_type=$1;
+ local img=$2;
+ local fsck_mode=$3;
+ local file_exist=$4;
+ local file_nochange=$5
+ local file_xattr_exist=$6;
+ local hard_link_exist=$7;
+ local hard_link_no_change=$8;
+ local hard_link_xattr_exist=$9;
+ local soft_link_exist=${10};
+ local dir_exist=${11};
+ local dir_file_no_change=${12};
+ local lost_found=${13};
+
+ echo "======================================================================"
+ echo "fsck $img_type, success_fsck_mode:$fsck_mode file_exist:$file_exist file_nochange:$file_nochange file_xattr_exist:$file_xattr_exist hard_link_exist:$hard_link_exist hard_link_no_change:$hard_link_no_change:hard_link_xattr_exist $hard_link_xattr_exist:soft_link_exist:$soft_link_exist dir_exist:$dir_exist $lost_found"
+
+ load_mtdram 1 16 || echo "cannot load mtdram"
+ mtdnum="$(find_mtd_device "$mtdram_patt")"
+
+ dmesg -c > /dev/null
+ gzip -f -k -d $TESTBINDIR/${img}.gz || fatal "gzip failed"
+ flash_eraseall /dev/mtd$mtdnum
+ dd if=$TESTBINDIR/$img of=/dev/mtd$mtdnum bs=1M
+ rm -f $TESTBINDIR/$img
+ modprobe ubi mtd="$mtdnum,0" || fatal "modprobe ubi fail"
+ modprobe ubifs || fatal "modprobe ubifs fail"
+
+ fsck.ubifs -a $DEV
+ let "ret=$?&~$FSCK_NONDESTRUCT"
+ if [[ $ret != $FSCK_OK ]]; then
+ if [[ "$fsck_mode" == "safe" ]]; then
+ fatal "The image should be fixed in $fsck_mode mode, but it fails"
+ fi
+
+ fsck.ubifs -y $DEV
+ let "ret=$?&~$FSCK_NONDESTRUCT"
+ if [[ $ret != $FSCK_OK ]]; then
+ if [[ "$fsck_mode" == "danger_default" ]]; then
+ fatal "The image should be fixed in $fsck_mode mode, but it fails"
+ fi
+
+ fsck.ubifs -yb $DEV
+ let "ret=$?&~$FSCK_NONDESTRUCT"
+ if [[ $ret != $FSCK_OK ]]; then
+ if [[ "$fsck_mode" == "danger_rebuild" ]]; then
+ fatal "The image should be fixed in $fsck_mode mode, but it fails"
+ fi
+
+ echo "fsck failed is expected, skip"
+
+ modprobe -r ubifs
+ modprobe -r ubi
+ modprobe -r mtdram
+ echo "----------------------------------------------------------------------"
+
+ return;
+ elif [[ "$fsck_mode" != "danger_rebuild" ]]; then
+ fatal "The image should not be fixed in $fsck_mode mode, but it succeeds"
+ fi
+ elif [[ "$fsck_mode" != "danger_default" ]]; then
+ fatal "The image should not be fixed in $fsck_mode mode, but it succeeds"
+ fi
+ elif [[ "$fsck_mode" != "safe" ]]; then
+ fatal "The image should not be fixed in $fsck_mode mode, but it succeeds"
+ fi
+
+ enable_chkfs
+
+ mount_ubifs $DEV $MNT
+ ret=$?
+ if [[ $ret != 0 ]]; then
+ fatal "mount failed $ret"
+ fi
+
+ du -sh $MNT > /dev/null # Make sure all files are accessible
+ ret=$?
+ if [[ $ret != 0 ]]; then
+ fatal "cannot access all files $ret"
+ fi
+
+ if [[ $file_exist == 1 ]]; then
+ if ! [ -f $MNT/$CORRUPT_FILE ]; then
+ fatal "$MNT/$CORRUPT_FILE is lost"
+ fi
+ else
+ if [ -f $MNT/$CORRUPT_FILE ]; then
+ fatal "$MNT/$CORRUPT_FILE should not exist"
+ fi
+ fi
+
+ md5_after=`md5sum $MNT/$CORRUPT_FILE 2>/dev/null | awk '{print $1}'`
+ if [[ $file_nochange == 1 ]]; then
+ if [[ $CORRUPT_FILE_MD5 != $md5_after ]]; then
+ fatal "content changed for $MNT/$CORRUPT_FILE"
+ fi
+ else
+ if [[ $CORRUPT_FILE_MD5 == $md5_after ]]; then
+ fatal "content not changed for $MNT/$CORRUPT_FILE"
+ fi
+ fi
+
+ xattr=`getfattr -n $XATTR_NAME $MNT/$CORRUPT_FILE 2>/dev/null | grep $XATTR_NAME | awk -F '=' '{ print $2 }'`
+ if [[ $file_xattr_exist == 1 ]]; then
+ if ! [[ "$xattr" =~ "$XATTR_VAL" ]]; then
+ fatal "wrong xattr $xattr for $MNT/$CORRUPT_DENT_NAME"
+ fi
+ else
+ if [[ "$xattr" =~ "$XATTR_VAL" ]]; then
+ fatal "xattr $xattr for $MNT/$CORRUPT_DENT_NAME should not exist"
+ fi
+ fi
+
+ if [[ $hard_link_exist == 1 ]]; then
+ if ! [ -f $MNT/$HARD_LINK_FILE ]; then
+ fatal "$MNT/$HARD_LINK_FILE should is lost"
+ fi
+ else
+ if [ -f $MNT/$HARD_LINK_FILE ]; then
+ fatal "$MNT/$HARD_LINK_FILE should not exist"
+ fi
+ fi
+
+ md5_after=`md5sum $MNT/$HARD_LINK_FILE 2>/dev/null | awk '{print $1}'`
+ if [[ $hard_link_no_change == 1 ]]; then
+ if [[ $CORRUPT_FILE_MD5 != $md5_after ]]; then
+ fatal "content changed for $MNT/$HARD_LINK_FILE"
+ fi
+ else
+ if [[ $CORRUPT_FILE_MD5 == $md5_after ]]; then
+ fatal "content not changed for $MNT/$HARD_LINK_FILE"
+ fi
+ fi
+
+ xattr=`getfattr -n $XATTR_NAME $MNT/$HARD_LINK_FILE 2>/dev/null | grep $XATTR_NAME | awk -F '=' '{ print $2 }'`
+ if [[ $hard_link_xattr_exist == 1 ]]; then
+ if ! [[ "$xattr" =~ "$XATTR_VAL" ]]; then
+ fatal "wrong xattr $xattr for $MNT/$HARD_LINK_FILE"
+ fi
+ else
+ if [[ "$xattr" =~ "$XATTR_VAL" ]]; then
+ fatal "xattr $xattr for $MNT/$HARD_LINK_FILE should not exist"
+ fi
+ fi
+
+ link=`stat -c %N $MNT/$SOFT_LINK_FILE 2>/dev/null | grep $SOFT_LINK_FILE | grep $CORRUPT_FILE`
+ if [[ $soft_link_exist == 1 ]]; then
+ if [[ "$link" == "" ]]; then
+ fatal "$MNT/$SOFT_LINK_FILE is lost"
+ fi
+ else
+ if [[ "$link" != "" ]]; then
+ fatal "$MNT/$SOFT_LINK_FILE should not exist"
+ fi
+ fi
+
+ if [[ $dir_exist == 1 ]]; then
+ if ! [ -d $MNT/$DIR ]; then
+ fatal "$MNT/$DIR is lost"
+ fi
+ if ! [ -d $MNT/$DIR/$DIR ]; then
+ fatal "$MNT/$DIR/$DIR is lost"
+ fi
+ if ! [ -f $MNT/$DIR/$FILE ]; then
+ fatal "$MNT/$DIR/$FILE is lost"
+ fi
+ f_md5=`md5sum $MNT/$DIR/$FILE 2>/dev/null | awk '{print $1}'`
+ if [[ $dir_file_no_change == 1 ]]; then
+ if [[ $FILE_MD5 != $f_md5 ]]; then
+ fatal "content changed for $MNT/$DIR/$FILE"
+ fi
+ else
+ if [[ $FILE_MD5 == $f_md5 ]]; then
+ fatal "content not changed for $MNT/$DIR/$FILE"
+ fi
+ fi
+ if ! [ -b $MNT/$DIR/$BLOCK_DEV ]; then
+ fatal "$MNT/$DIR/$BLOCK_DEV is lost"
+ fi
+ major=`stat -c %t $MNT/$DIR/$BLOCK_DEV`
+ minor=`stat -c %T $MNT/$DIR/$BLOCK_DEV`
+ if [[ $major != 1 ]] || [[ $minor != 2 ]]; then
+ echo "major/minor changed for $MNT/$DIR/$BLOCK_DEV"
+ fi
+ if ! [ -c $MNT/$DIR/$CHAR_DEV ]; then
+ fatal "$MNT/$DIR/$CHAR_DEV is lost"
+ fi
+ major=`stat -c %t $MNT/$DIR/$CHAR_DEV`
+ minor=`stat -c %T $MNT/$DIR/$CHAR_DEV`
+ if [[ $major != 0 ]] || [[ $minor != 1 ]]; then
+ echo "major/minor changed for $MNT/$DIR/$CHAR_DEV"
+ fi
+ else
+ if [ -d $MNT/$DIR ]; then
+ fatal "$MNT/$DIR should not exist"
+ fi
+ fi
+
+ if [[ "$lost_found" == "no lost+found" ]]; then
+ if [ -d $MNT/$LOST_FOUND ]; then
+ fatal "$MNT/$LOST_FOUND should not exist"
+ fi
+ elif [[ "$lost_found" == "lost+found is regular" ]]; then
+ if ! [ -f $MNT/$LOST_FOUND ]; then
+ fatal "$MNT/$LOST_FOUND is not regular file"
+ fi
+ else
+ if ! [ -d $MNT/$LOST_FOUND ]; then
+ fatal "$MNT/$LOST_FOUND is lost"
+ fi
+
+ if ! [ -f $MNT/$LOST_FOUND/${FILE_INUM}_0 ]; then
+ fatal "$MNT/$LOST_FOUND/${FILE_INUM}_0 is lost"
+ fi
+ if [[ "$lost_found" == "lost+found has one" ]]; then
+ f_md5=`md5sum $MNT/$LOST_FOUND/${FILE_INUM}_0 2>/dev/null | awk '{print $1}'`
+ if [[ $FILE_MD5 != $f_md5 ]]; then
+ fatal "content changed for $MNT/$LOST_FOUND/${FILE_INUM}_0"
+ fi
+ elif [[ "$lost_found" == "lost+found has two" ]]; then
+ f_md5=`md5sum $MNT/$LOST_FOUND/${CORRUPT_FILE_INUM}_0 2>/dev/null | awk '{print $1}'`
+ if [[ $CORRUPT_FILE_MD5 != $f_md5 ]]; then
+ fatal "content changed for $MNT/$LOST_FOUND/${CORRUPT_FILE_INUM}_0"
+ fi
+ f_md5=`md5sum $MNT/$LOST_FOUND/${FILE_INUM}_0 2>/dev/null | awk '{print $1}'`
+ if [[ $FILE_MD5 != $f_md5 ]]; then
+ fatal "content changed for $MNT/$LOST_FOUND/${FILE_INUM}_0"
+ fi
+ else
+ if ! [ -f $MNT/$LOST_FOUND/${FILE_INUM}_1 ]; then
+ fatal "$MNT/$LOST_FOUND/${FILE_INUM}_1 is lost"
+ fi
+ f_md5=`md5sum $MNT/$LOST_FOUND/${FILE_INUM}_1 2>/dev/null | awk '{print $1}'`
+ if [[ $FILE_MD5 != $f_md5 ]]; then
+ fatal "content changed for $MNT/$LOST_FOUND/${FILE_INUM}_1"
+ fi
+ fi
+ fi
+
+ umount $MNT
+ res=$?
+ if [[ $res != 0 ]]
+ then
+ fatal "unmount fail $res"
+ fi
+
+ disable_chkfs
+
+ check_err_msg
+
+ modprobe -r ubifs
+ modprobe -r ubi
+ modprobe -r mtdram
+
+ echo "----------------------------------------------------------------------"
+}
+
+start_t=$(date +%s)
+echo "Do inconsistent UBIFS images fscking test"
+fsck_image "good image" good "safe" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad sb fanout image" sb_fanout "none" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad sb fmt_version image" sb_fmt_version "none" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad sb leb_size image" sb_leb_size "none" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad sb log_lebs image" sb_log_lebs "none" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad sb min_io_size image" sb_min_io_size "none" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad master highest_inum image" master_highest_inum "danger_rebuild" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad master lpt image" master_lpt "danger_rebuild" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad master tnc image" master_tnc "danger_rebuild" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad master total_dead image" master_total_dead "safe" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad master total_dirty image" master_total_dirty "safe" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad master total_free image" master_total_free "safe" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "corrupted journal log area image" journal_log "danger_rebuild" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "corrupted journal bud area image" journal_bud "danger_default" 1 0 1 1 0 1 1 1 0 "no lost+found"
+fsck_image "bad orphan node image" orphan_node "danger_default" 0 0 0 0 0 0 1 1 1 "no lost+found"
+fsck_image "bad lpt dirty image" lpt_dirty "safe" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad lpt lpt_flags image" lpt_flags "safe" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad lpt free image" lpt_free "safe" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad lpt pos image" lpt_pos "safe" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad lprops table dirty image" ltab_dirty "safe" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad lprops table free image" ltab_free "safe" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad index size image" index_size "safe" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad tnc lv0 key image" tnc_lv0_key "danger_rebuild" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad tnc lv0 len image" tnc_lv0_len "danger_rebuild" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad tnc lv0 pos image" tnc_lv0_pos "danger_rebuild" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad tnc non-leaf key image" tnc_noleaf_key "danger_rebuild" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad tnc non-leaf len image" tnc_noleaf_len "danger_rebuild" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad tnc non-leaf pos image" tnc_noleaf_pos "danger_rebuild" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "corrupted leb for file data image" corrupted_data_leb "danger_default" 1 0 1 1 0 1 1 1 1 "no lost+found"
+fsck_image "corrupted leb for TNC image" corrupted_idx_leb "danger_rebuild" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad inode data image" inode_data "danger_default" 1 0 1 1 0 1 1 1 1 "no lost+found"
+fsck_image "bad inode mode image" inode_mode "danger_default" 0 0 0 0 0 0 1 1 1 "no lost+found"
+fsck_image "bad inode nlink image" inode_nlink "safe" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad inode size image" inode_size "safe" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad inode xattr_cnt image" inode_xcnt "safe" 1 1 1 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad softlink inode mode image" soft_link_inode_mode "danger_default" 1 1 1 1 1 1 0 1 1 "no lost+found"
+fsck_image "bad softlink inode data_len image" soft_link_data_len "danger_default" 1 1 1 1 1 1 0 1 1 "no lost+found"
+fsck_image "bad dentry key image" dentry_key "danger_default" 0 0 0 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad dentry nlen image" dentry_nlen "danger_default" 0 0 0 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad dentry type image" dentry_type "danger_default" 0 0 0 1 1 1 1 1 1 "no lost+found"
+fsck_image "bad xattr inode flags image" xinode_flags "danger_default" 1 1 0 1 1 0 1 1 1 "no lost+found"
+fsck_image "bad xattr inode key image" xinode_key "danger_default" 1 1 0 1 1 0 1 1 1 "no lost+found"
+fsck_image "bad xattr inode mode image" xinode_mode "danger_default" 1 1 0 1 1 0 1 1 1 "no lost+found"
+fsck_image "bad xattr dentry key image" xentry_key "danger_default" 1 1 0 1 1 0 1 1 1 "no lost+found"
+fsck_image "bad xattr dentry nlen image" xentry_nlen "danger_default" 1 1 0 1 1 0 1 1 1 "no lost+found"
+fsck_image "bad xattr dentry type image" xentry_type "danger_default" 1 1 0 1 1 0 1 1 1 "no lost+found"
+fsck_image "bad xattr host image" xent_host "danger_default" 0 0 0 0 0 0 1 1 1 "no lost+found"
+fsck_image "dir has too many dentry image" dir_many_dentry "danger_default" 1 1 1 0 0 0 1 1 1 "no lost+found"
+fsck_image "bad dir image" dir_lost "danger_default" 1 1 1 1 1 1 1 0 1 "lost+found has one"
+fsck_image "bad dir and duplicated file name in lost+found image" dir_lost_duplicated "danger_default" 1 1 1 1 1 1 1 0 1 "lost+found has duplicated files"
+fsck_image "bad dir and lost+found image" dir_lost_not_recover "danger_default" 1 1 1 1 1 1 1 0 1 "lost+found is regular"
+fsck_image "bad root dir image" root_dir "danger_default" 0 0 0 0 0 0 0 0 1 "lost+found has two"
+fsck_image "empty TNC image" empty_tnc "danger_rebuild" 0 0 0 0 0 0 0 0 1 "no lost+found"
+end_t=$(date +%s)
+time_cost=$(( end_t - start_t ))
+echo "Success, cost $time_cost seconds"
+exit 0
diff --git a/tests/ubifs_tools-tests/fsck_tests/powercut_fsck_mount.sh.in b/tests/ubifs_tools-tests/fsck_tests/powercut_fsck_mount.sh.in
new file mode 100755
index 0000000..ac7128b
--- /dev/null
+++ b/tests/ubifs_tools-tests/fsck_tests/powercut_fsck_mount.sh.in
@@ -0,0 +1,148 @@
+#!/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 & powercut & unmount
+# 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 &
+ sleep $((RANDOM % 120))
+ powercut
+
+ 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
+
+ fsck.ubifs -a $DEV 2>&1 > $LOG_FILE
+ res=$?
+ cat $LOG_FILE
+ if [[ $res != $FSCK_OK ]]
+ then
+ # Powercut during layout_leb_in_gaps may change index LEBs
+ # without updating LPT.
+ idx_log=`cat $LOG_FILE | grep "Inconsistent properties" | grep "is_idx 1"`
+ # The lpt nodes could be parsed incorrectly because the lpt disk
+ # layout is too simple. See details in
+ # https://lore.kernel.org/linux-mtd/97ca7fe4-4ad4-edd1-e97a-1d540aeabe2d@huawei.com/
+ lpt_log=`cat $LOG_FILE | grep "dbg_check_ltab_lnum: invalid empty space in LEB"`
+ if [[ "$idx_log" == "" ]] && [[ "$lpt_log" == "" ]]; then
+ fatal "fsck fail $res"
+ fi
+ if [[ $res != $FSCK_NONDESTRUCT ]]; then
+ fatal "fsck fail $res"
+ fi
+ fi
+
+ dmesg -c > /dev/null # powercut could reproduce error messages
+
+ enable_chkfs
+
+ mount_ubifs $DEV $MNT "noauthentication" "noatime"
+ res=$?
+ if [[ $res != 0 ]]
+ then
+ fatal "mount fail $res"
+ fi
+
+ if [[ "$encryption" == "encrypted" ]]; then
+ encryption_set_key $MNT
+ 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
+
+ umount $MNT
+ res=$?
+ if [[ $res != 0 ]]
+ then
+ fatal "unmount fail $res"
+ fi
+
+ check_err_msg
+
+ modprobe -r ubifs
+ modprobe -r ubi
+ modprobe -r $simulator
+
+ echo "----------------------------------------------------------------------"
+}
+
+check_fsstress
+start_t=$(date +%s)
+echo "Do powercut+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
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
index 0000000..64760c9
--- /dev/null
+++ b/tests/ubifs_tools-tests/fsck_tests/random_corrupted_fsck.sh.in
@@ -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
diff --git a/tests/ubifs_tools-tests/images/corrupted_data_leb.gz b/tests/ubifs_tools-tests/images/corrupted_data_leb.gz
new file mode 100644
index 0000000..ebb98a4
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/corrupted_data_leb.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/corrupted_idx_leb.gz b/tests/ubifs_tools-tests/images/corrupted_idx_leb.gz
new file mode 100644
index 0000000..446f811
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/corrupted_idx_leb.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/dentry_key.gz b/tests/ubifs_tools-tests/images/dentry_key.gz
new file mode 100644
index 0000000..bc313b5
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/dentry_key.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/dentry_nlen.gz b/tests/ubifs_tools-tests/images/dentry_nlen.gz
new file mode 100644
index 0000000..4e5c826
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/dentry_nlen.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/dentry_type.gz b/tests/ubifs_tools-tests/images/dentry_type.gz
new file mode 100644
index 0000000..e67348d
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/dentry_type.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/dir_lost.gz b/tests/ubifs_tools-tests/images/dir_lost.gz
new file mode 100644
index 0000000..fd42040
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/dir_lost.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/dir_lost_duplicated.gz b/tests/ubifs_tools-tests/images/dir_lost_duplicated.gz
new file mode 100644
index 0000000..09def92
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/dir_lost_duplicated.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/dir_lost_not_recover.gz b/tests/ubifs_tools-tests/images/dir_lost_not_recover.gz
new file mode 100644
index 0000000..6fe82bb
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/dir_lost_not_recover.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/dir_many_dentry.gz b/tests/ubifs_tools-tests/images/dir_many_dentry.gz
new file mode 100644
index 0000000..f027bfc
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/dir_many_dentry.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/empty_tnc.gz b/tests/ubifs_tools-tests/images/empty_tnc.gz
new file mode 100644
index 0000000..7e85a8c
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/empty_tnc.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/good.gz b/tests/ubifs_tools-tests/images/good.gz
new file mode 100644
index 0000000..686e949
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/good.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/index_size.gz b/tests/ubifs_tools-tests/images/index_size.gz
new file mode 100644
index 0000000..0ebcf59
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/index_size.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/inode_data.gz b/tests/ubifs_tools-tests/images/inode_data.gz
new file mode 100644
index 0000000..f8135dc
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/inode_data.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/inode_mode.gz b/tests/ubifs_tools-tests/images/inode_mode.gz
new file mode 100644
index 0000000..1bdbb26
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/inode_mode.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/inode_nlink.gz b/tests/ubifs_tools-tests/images/inode_nlink.gz
new file mode 100644
index 0000000..19461d9
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/inode_nlink.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/inode_size.gz b/tests/ubifs_tools-tests/images/inode_size.gz
new file mode 100644
index 0000000..aa7574c
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/inode_size.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/inode_xcnt.gz b/tests/ubifs_tools-tests/images/inode_xcnt.gz
new file mode 100644
index 0000000..4bc5ac2
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/inode_xcnt.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/journal_bud.gz b/tests/ubifs_tools-tests/images/journal_bud.gz
new file mode 100644
index 0000000..37cf453
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/journal_bud.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/journal_log.gz b/tests/ubifs_tools-tests/images/journal_log.gz
new file mode 100644
index 0000000..e1ddc88
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/journal_log.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/lpt_dirty.gz b/tests/ubifs_tools-tests/images/lpt_dirty.gz
new file mode 100644
index 0000000..b7381c3
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/lpt_dirty.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/lpt_flags.gz b/tests/ubifs_tools-tests/images/lpt_flags.gz
new file mode 100644
index 0000000..baf6097
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/lpt_flags.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/lpt_free.gz b/tests/ubifs_tools-tests/images/lpt_free.gz
new file mode 100644
index 0000000..abc46fd
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/lpt_free.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/lpt_pos.gz b/tests/ubifs_tools-tests/images/lpt_pos.gz
new file mode 100644
index 0000000..d050f18
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/lpt_pos.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/ltab_dirty.gz b/tests/ubifs_tools-tests/images/ltab_dirty.gz
new file mode 100644
index 0000000..56dabee
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/ltab_dirty.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/ltab_free.gz b/tests/ubifs_tools-tests/images/ltab_free.gz
new file mode 100644
index 0000000..985e275
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/ltab_free.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/master_highest_inum.gz b/tests/ubifs_tools-tests/images/master_highest_inum.gz
new file mode 100644
index 0000000..08ed044
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/master_highest_inum.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/master_lpt.gz b/tests/ubifs_tools-tests/images/master_lpt.gz
new file mode 100644
index 0000000..4b205a2
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/master_lpt.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/master_tnc.gz b/tests/ubifs_tools-tests/images/master_tnc.gz
new file mode 100644
index 0000000..4219a5e
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/master_tnc.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/master_total_dead.gz b/tests/ubifs_tools-tests/images/master_total_dead.gz
new file mode 100644
index 0000000..165d787
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/master_total_dead.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/master_total_dirty.gz b/tests/ubifs_tools-tests/images/master_total_dirty.gz
new file mode 100644
index 0000000..9416bbd
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/master_total_dirty.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/master_total_free.gz b/tests/ubifs_tools-tests/images/master_total_free.gz
new file mode 100644
index 0000000..e6e942f
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/master_total_free.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/orphan_node.gz b/tests/ubifs_tools-tests/images/orphan_node.gz
new file mode 100644
index 0000000..901d75d
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/orphan_node.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/root_dir.gz b/tests/ubifs_tools-tests/images/root_dir.gz
new file mode 100644
index 0000000..d45e4dc
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/root_dir.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/sb_fanout.gz b/tests/ubifs_tools-tests/images/sb_fanout.gz
new file mode 100644
index 0000000..520fd09
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/sb_fanout.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/sb_fmt_version.gz b/tests/ubifs_tools-tests/images/sb_fmt_version.gz
new file mode 100644
index 0000000..c6309e1
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/sb_fmt_version.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/sb_leb_size.gz b/tests/ubifs_tools-tests/images/sb_leb_size.gz
new file mode 100644
index 0000000..a04ed7b
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/sb_leb_size.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/sb_log_lebs.gz b/tests/ubifs_tools-tests/images/sb_log_lebs.gz
new file mode 100644
index 0000000..9113fe4
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/sb_log_lebs.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/sb_min_io_size.gz b/tests/ubifs_tools-tests/images/sb_min_io_size.gz
new file mode 100644
index 0000000..788096d
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/sb_min_io_size.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/soft_link_data_len.gz b/tests/ubifs_tools-tests/images/soft_link_data_len.gz
new file mode 100644
index 0000000..10414a7
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/soft_link_data_len.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/soft_link_inode_mode.gz b/tests/ubifs_tools-tests/images/soft_link_inode_mode.gz
new file mode 100644
index 0000000..e333611
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/soft_link_inode_mode.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/tnc_lv0_key.gz b/tests/ubifs_tools-tests/images/tnc_lv0_key.gz
new file mode 100644
index 0000000..bcc8ca2
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/tnc_lv0_key.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/tnc_lv0_len.gz b/tests/ubifs_tools-tests/images/tnc_lv0_len.gz
new file mode 100644
index 0000000..1c64d79
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/tnc_lv0_len.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/tnc_lv0_pos.gz b/tests/ubifs_tools-tests/images/tnc_lv0_pos.gz
new file mode 100644
index 0000000..5816123
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/tnc_lv0_pos.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/tnc_noleaf_key.gz b/tests/ubifs_tools-tests/images/tnc_noleaf_key.gz
new file mode 100644
index 0000000..fc7c0ed
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/tnc_noleaf_key.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/tnc_noleaf_len.gz b/tests/ubifs_tools-tests/images/tnc_noleaf_len.gz
new file mode 100644
index 0000000..2d0f80d
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/tnc_noleaf_len.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/tnc_noleaf_pos.gz b/tests/ubifs_tools-tests/images/tnc_noleaf_pos.gz
new file mode 100644
index 0000000..1a05959
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/tnc_noleaf_pos.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/xent_host.gz b/tests/ubifs_tools-tests/images/xent_host.gz
new file mode 100644
index 0000000..b2aef46
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/xent_host.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/xentry_key.gz b/tests/ubifs_tools-tests/images/xentry_key.gz
new file mode 100644
index 0000000..b4fa6d5
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/xentry_key.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/xentry_nlen.gz b/tests/ubifs_tools-tests/images/xentry_nlen.gz
new file mode 100644
index 0000000..e351280
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/xentry_nlen.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/xentry_type.gz b/tests/ubifs_tools-tests/images/xentry_type.gz
new file mode 100644
index 0000000..e0c5763
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/xentry_type.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/xinode_flags.gz b/tests/ubifs_tools-tests/images/xinode_flags.gz
new file mode 100644
index 0000000..34d3ff7
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/xinode_flags.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/xinode_key.gz b/tests/ubifs_tools-tests/images/xinode_key.gz
new file mode 100644
index 0000000..c92956c
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/xinode_key.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/images/xinode_mode.gz b/tests/ubifs_tools-tests/images/xinode_mode.gz
new file mode 100644
index 0000000..0e52648
--- /dev/null
+++ b/tests/ubifs_tools-tests/images/xinode_mode.gz
Binary files differ
diff --git a/tests/ubifs_tools-tests/lib/common.sh.in b/tests/ubifs_tools-tests/lib/common.sh.in
new file mode 100755
index 0000000..8d1b3c0
--- /dev/null
+++ b/tests/ubifs_tools-tests/lib/common.sh.in
@@ -0,0 +1,359 @@
+#!/bin/sh
+# Copyright (c), 2024, Huawei Technologies Co, Ltd.
+# Author: Zhihao Cheng <chengzhihao1@huawei.com>
+#
+# Provide basic functions.
+
+UBI_NUM=0
+DEV=/dev/ubi0_0
+MNT=/mnt/test_file_system
+TMP_FILE=/tmp/ubifs_test_file
+TMP_MNT=/tmp/ubifs_tmp_mnt
+LOG_FILE=/tmp/ubifs_log
+KEY_FILE=/tmp/key
+IMG_FILE=ubifs.img
+nandsim_patt="NAND simulator"
+mtdram_patt="mtdram test device"
+
+# fsck returning code
+FSCK_OK=0 # No errors
+FSCK_NONDESTRUCT=1 # File system errors corrected
+FSCK_REBOOT=2 # System should be rebooted
+FSCK_UNCORRECTED=4 # File system errors left uncorrected
+FSCK_ERROR=8 # Operational error
+FSCK_USAGE=16 # Usage or syntax error
+FSCK_CANCELED=32 # Aborted with a signal or ^
+FSCK_LIBRARY=128 # Shared library error
+
+function fatal()
+{
+ echo "Error: $1" 1>&2
+ exit 1
+}
+
+# All loaded modules(mtdram/nandsim/ubi/ubifs) won't be removed if errors
+# happen, it is useful to debug based on the UBIFS image.
+function cleanup_handler()
+{
+ local ret="$1"
+
+ umount $TMP_MNT >/dev/null 2>&1 ||:
+ rm -rf $TMP_MNT >/dev/null 2>&1 ||:
+ if [ "$ret" == "0" ]; then
+ umount $MNT >/dev/null 2>&1 ||:
+ modprobe -r ubifs >/dev/null 2>&1 ||:
+ modprobe -r ubi >/dev/null 2>&1 ||:
+ modprobe -r nandsim >/dev/null 2>&1 ||:
+ modprobe -r mtdram >/dev/null 2>&1 ||:
+ rm -rf $MNT >/dev/null 2>&1 ||:
+ rm -f $TMP_FILE >/dev/null 2>&1 ||:
+ rm -f $KEY_FILE >/dev/null 2>&1 ||:
+ rm -f $LOG_FILE >/dev/null 2>&1 ||:
+ rm -f $IMG_FILE >/dev/null 2>&1 ||:
+ exit 0
+ else
+ exit 1
+ fi
+}
+trap 'cleanup_handler $?' EXIT
+trap 'cleanup_handler 1' HUP PIPE INT QUIT TERM
+
+function find_mtd_device()
+{
+ printf "%s" "$(grep "$1" /proc/mtd | sed -e "s/^mtd\([0-9]\+\):.*$/\1/")"
+}
+
+function powercut()
+{
+ dmesg -c > /dev/null
+ echo 1 > /sys/kernel/debug/ubifs/tst_recovery;
+ while true;
+ do
+ msg=`dmesg -c | grep "Power cut emulated"`;
+ if [[ "$msg" != "" ]];
+ then
+ break;
+ fi
+ ro_error=`cat /sys/kernel/debug/ubifs/ubi${UBI_NUM}_0/ro_error`
+ if [[ $ro_error != 0 ]]; then
+ break;
+ fi
+ done
+ echo 0 > /sys/kernel/debug/ubifs/tst_recovery
+}
+
+# Load mtdram with specified size and PEB size
+# Usage: load_mtdram <flash size> <PEB size>
+# 1. Flash size is specified in MiB
+# 2. PEB size is specified in KiB
+function load_mtdram()
+{
+ local size="$1"; shift
+ local peb_size="$1"; shift
+
+ size="$(($size * 1024))"
+ modprobe mtdram total_size="$size" erase_size="$peb_size"
+}
+
+function check_fsstress()
+{
+ cmd=`fsstress | grep "op_name"`
+ if ! [[ "$cmd" =~ "op_name" ]]; then
+ fatal "fsstress is not found"
+ fi
+}
+
+# Check error messages
+function check_err_msg()
+{
+ msg=`dmesg | grep -E "dump_stack|UBIFS error|switched to read-only mode"`;
+ if [[ "$msg" != "" ]]
+ then
+ dmesg
+ fatal "error message detected!"
+ fi
+ dmesg -c > /dev/null
+}
+
+# Iterate all files under certain dir
+# $1: dir
+# $2: "md5sum" means that need record md5 for regular file, otherwise don't record md5 for regular file
+function read_dir() {
+ for file in `ls -a $1`
+ do
+ cur_f=$1"/"$file
+ if [ -b $cur_f ]
+ then
+ major=`stat -c %t $cur_f`
+ minor=`stat -c %T $cur_f`
+ echo "block $cur_f $major $minor" >> $TMP_FILE
+ elif [ -c $cur_f ]
+ then
+ major=`stat -c %t $cur_f`
+ minor=`stat -c %T $cur_f`
+ echo "char $cur_f $major $minor" >> $TMP_FILE
+ elif [ -L $cur_f ]
+ then
+ link=`stat -c %N $cur_f`
+ echo "symlink $cur_f $link" >> $TMP_FILE
+ elif [ -S $cur_f ]
+ then
+ echo "sock $cur_f" >> $TMP_FILE
+ elif [ -p $cur_f ]
+ then
+ echo "fifo $cur_f" >> $TMP_FILE
+ elif [ -f $cur_f ]
+ then
+ sz=`stat -c %s $cur_f`
+ if [[ "$2" != "md5sum" ]]; then
+ echo "reg $cur_f $sz" >> $TMP_FILE
+ else
+ md5=`md5sum $cur_f | awk '{print $1}'`
+ echo "reg $cur_f $md5 $sz" >> $TMP_FILE
+ fi
+ elif [ -d $cur_f ]
+ then
+ if [[ $file != '.' && $file != '..' ]]
+ then
+ echo "dir $cur_f" >> $TMP_FILE
+ read_dir $1"/"$file $2
+ fi
+ else
+ fatal "record unknown file type $cur_f"
+ fi
+ done
+}
+
+# Check whether there are files lost after fsck/mkfs
+# $1: "md5sum" means need record md5 for regular file, otherwise don't check md5 for regular file
+function parse_dir()
+{
+ while read line
+ do
+ array=(${line//\ / });
+ f_type=${array[0]};
+ cur_f=${array[1]};
+ cur_info=""
+ if [[ "$f_type" =~ "block" ]]
+ then
+ major=`stat -c %t $cur_f`
+ minor=`stat -c %T $cur_f`
+ cur_info="block $cur_f $major $minor"
+ elif [[ "$f_type" =~ "char" ]]
+ then
+ major=`stat -c %t $cur_f`
+ minor=`stat -c %T $cur_f`
+ cur_info="char $cur_f $major $minor"
+ elif [[ "$f_type" =~ "symlink" ]]
+ then
+ link=`stat -c %N $cur_f`
+ cur_info="symlink $cur_f $link"
+ elif [[ "$f_type" =~ "sock" ]]
+ then
+ cur_info="sock $cur_f"
+ elif [[ "$f_type" =~ "fifo" ]]
+ then
+ cur_info="fifo $cur_f"
+ elif [[ "$f_type" =~ "reg" ]]
+ then
+ sz=`stat -c %s $cur_f`
+ if [[ "$1" != "md5sum" ]]; then
+ cur_info="reg $cur_f $sz"
+ else
+ md5=`md5sum $cur_f | awk '{print $1}'`
+ cur_info="reg $cur_f $md5 $sz"
+ fi
+ elif [[ "$f_type" =~ "dir" ]]
+ then
+ cur_info="dir $cur_f"
+ else
+ fatal "parse unknown file type $cur_f"
+ fi
+ if [[ "$cur_info" != "$line" ]]
+ then
+ fatal "current info $cur_info, but expect $line"
+ fi
+ done < $TMP_FILE
+}
+
+function authentication()
+{
+ keyctl clear @s
+ res=$?
+ if [[ $res != 0 ]]; then
+ fatal "keyctl is not found"
+ fi
+ keyctl add logon ubifs:foo 12345678901234567890123456789012 @s
+}
+
+function encryption_gen_key()
+{
+ # CONFIG_FS_ENCRYPTION=y
+ head -c 64 /dev/urandom > $KEY_FILE
+ cmd=`fscryptctl -h | grep "set_policy"`
+ if ! [[ "$cmd" =~ "set_policy" ]]; then
+ fatal "fscryptctl is not found"
+ fi
+}
+
+function encryption_set_key()
+{
+ mnt=$1
+ ignore_err=$2
+ # https://github.com/google/fscryptctl
+ key=$(fscryptctl add_key $mnt < $KEY_FILE)
+ fscryptctl set_policy $key $mnt
+ #fscryptctl get_policy $mnt
+ ret=$?
+ if [[ $ret != 0 && $ignore_err != 1 ]]; then
+ fatal "set encryption policy failed"
+ fi
+}
+
+function mount_ubifs()
+{
+ local dev=$1;
+ local mnt=$2;
+ local auth=$3;
+ local noatime=$4;
+ local option="";
+ if [[ "$noatime" == "noatime" ]]; then
+ option="-o noatime"
+ fi
+ if [[ "$auth" == "authentication" ]]; then
+ authentication
+ if [[ "$option" == "" ]]; then
+ option="-o auth_key=ubifs:foo,auth_hash_name=sha256"
+ else
+ option="$option,auth_key=ubifs:foo,auth_hash_name=sha256"
+ fi
+ fi
+ mount -t ubifs $option $dev $mnt
+}
+
+function enable_chkfs()
+{
+ echo 1 > /sys/kernel/debug/ubifs/chk_fs
+ echo 1 > /sys/kernel/debug/ubifs/chk_general
+ echo 1 > /sys/kernel/debug/ubifs/chk_index
+ echo 1 > /sys/kernel/debug/ubifs/chk_lprops
+ echo 1 > /sys/kernel/debug/ubifs/chk_orphans
+}
+
+function disable_chkfs()
+{
+ echo 0 > /sys/kernel/debug/ubifs/chk_fs
+ echo 0 > /sys/kernel/debug/ubifs/chk_general
+ echo 0 > /sys/kernel/debug/ubifs/chk_index
+ echo 0 > /sys/kernel/debug/ubifs/chk_lprops
+ echo 0 > /sys/kernel/debug/ubifs/chk_orphans
+}
+
+function inject_mem_err()
+{
+ # CONFIG_FAILSLAB=y
+ # CONFIG_FAIL_PAGE_ALLOC=y
+ local pid=$1;
+
+ if ! [ -f /sys/kernel/debug/failslab/probability ]; then
+ fatal "failslab is not enabled, injection failed"
+ fi
+ if ! [ -f /sys/kernel/debug/fail_page_alloc/probability ]; then
+ fatal "fail_page_alloc is not enabled, injection failed"
+ fi
+
+ echo 1 > /proc/$pid/make-it-fail
+
+ echo Y > /sys/kernel/debug/failslab/task-filter
+ echo 1 > /sys/kernel/debug/failslab/probability # 1% failure
+ echo 10000 > /sys/kernel/debug/failslab/times
+ echo 1 > /sys/kernel/debug/failslab/verbose
+ echo N > /sys/kernel/debug/failslab/ignore-gfp-wait
+
+ echo Y > /sys/kernel/debug/fail_page_alloc/task-filter
+ echo 1 > /sys/kernel/debug/fail_page_alloc/probability
+ echo 10000 > /sys/kernel/debug/fail_page_alloc/times
+ echo 0 > /sys/kernel/debug/fail_page_alloc/verbose
+ echo N > /sys/kernel/debug/fail_page_alloc/ignore-gfp-wait
+}
+
+function cancel_mem_err()
+{
+ echo 0 > /sys/kernel/debug/failslab/probability
+ echo 0 > /sys/kernel/debug/failslab/times
+ echo 0 > /sys/kernel/debug/failslab/verbose
+ echo N > /sys/kernel/debug/failslab/task-filter
+ echo Y > /sys/kernel/debug/failslab/ignore-gfp-wait
+
+ echo 0 > /sys/kernel/debug/fail_page_alloc/probability
+ echo 0 > /sys/kernel/debug/fail_page_alloc/times
+ echo 1 > /sys/kernel/debug/fail_page_alloc/verbose
+ echo N > /sys/kernel/debug/fail_page_alloc/task-filter
+ echo Y > /sys/kernel/debug/fail_page_alloc/ignore-gfp-wait
+}
+
+function inject_io_err()
+{
+ if ! [ -f /sys/kernel/debug/ubi/ubi$UBI_NUM/tst_emulate_io_failures ]; then
+ fatal "tst_emulate_io_failures is not enabled, skip injection"
+ fi
+
+ echo 1 > /sys/kernel/debug/ubi/ubi$UBI_NUM/tst_emulate_io_failures
+}
+
+function cancel_io_err()
+{
+ echo 0 > /sys/kernel/debug/ubi/ubi$UBI_NUM/tst_emulate_io_failures
+}
+
+if ! [ -d $MNT ]; then
+ mkdir -p $MNT
+fi
+if ! [ -d $TMP_MNT ]; then
+ mkdir -p $TMP_MNT
+fi
+
+modprobe ubi || fatal "common.sh: cannot load ubi"
+modprobe ubifs || fatal "common.sh: cannot load ubifs"
+modprobe -r ubifs
+modprobe -r ubi
diff --git a/tests/ubifs_tools-tests/mkfs_tests/build_fs_from_dir.sh.in b/tests/ubifs_tools-tests/mkfs_tests/build_fs_from_dir.sh.in
new file mode 100755
index 0000000..0b22856
--- /dev/null
+++ b/tests/ubifs_tools-tests/mkfs_tests/build_fs_from_dir.sh.in
@@ -0,0 +1,174 @@
+#!/bin/sh
+# Copyright (c), 2024, Huawei Technologies Co, Ltd.
+# Author: Zhihao Cheng <chengzhihao1@huawei.com>
+#
+# Test Description:
+# Initialize UBIFS image from a given directory, then check whether the
+# fs content in mounted UBIFS is consistent with the original directory.
+# Both UBI volume and file are chosen as storage mediums to test.
+# Running time: 10min
+
+TESTBINDIR=@TESTBINDIR@
+source $TESTBINDIR/common.sh
+
+function run_test()
+{
+ local simulator="$1";
+ local size="$2";
+ local peb_size="$3";
+ local page_size="$4";
+ local vid_offs=$page_size;
+ local encryption=$5;
+ local test_medium=$6;
+ local space_fix=$7;
+ local need_fsck=$8;
+ local double_mkfs=$9;
+ local leb_size=$(($(($peb_size*1024))-$page_size));
+ VIDHDR_SZ=64;
+
+ option=""
+ if [[ "$space_fix" == "fix_space" ]]; then
+ option="-F"
+ fi
+ echo "======================================================================"
+ printf "%s" "$simulator: ${size}MiB PEB size ${peb_size}KiB"
+ if [ "$simulator" = "mtdram" ]; then
+ page_size=8
+ leb_size=$(($leb_size-$VIDHDR_SZ))
+ else
+ leb_size=$(($leb_size-$page_size))
+ fi
+ printf " %s" "page size ${page_size}Bytes"
+ printf " $encryption $test_medium $space_fix $need_fsck $double_mkfs\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
+
+ dmesg -c > /dev/null
+ flash_eraseall /dev/mtd$mtdnum
+ modprobe ubi mtd="$mtdnum,$vid_offs" || fatal "modprobe ubi fail"
+ ubimkvol -N vol_test -m -n 0 /dev/ubi$UBI_NUM || fatal "mkvol fail"
+ modprobe ubifs || fatal "modprobe ubifs fail"
+ if [[ "$encryption" == "encrypted" ]]; then
+ encryption_gen_key
+ option="$option --cipher AES-256-XTS --key $KEY_FILE"
+ fi
+
+ if [[ "$test_medium" == "volume" ]]; then
+ mkfs.ubifs $option -m${page_size} -c 1024 -e $leb_size -f 4 -r $TMP_MNT $DEV
+ if [[ $? != 0 ]]; then
+ fatal "mkfs failed"
+ fi
+ if [[ "$double_mkfs" == "double_format" ]]; then
+ mkfs.ubifs -y $option -m${page_size} -c 1024 -e $leb_size -f 4 -r $TMP_MNT $DEV
+ if [[ $? != 0 ]]; then
+ fatal "mkfs failed"
+ fi
+ fi
+ else
+ mkfs.ubifs $option -m${page_size} -c 1024 -e $leb_size -f 4 -r $TMP_MNT -o $IMG_FILE
+ if [[ $? != 0 ]]; then
+ fatal "mkfs failed"
+ fi
+ ubiupdatevol $DEV $IMG_FILE
+ if [[ $? != 0 ]]; then
+ fatal "ubiupdatevol failed"
+ fi
+ fi
+
+ if [[ "$need_fsck" == "do_fsck" ]]; then
+ fsck.ubifs -a $DEV # 'fsck.ubifs $DEV' is fine too.
+ res=$?
+ if [[ $res != $FSCK_OK ]]
+ then
+ fatal "fsck expects result $FSCK_OK, but $res is returned"
+ fi
+ fi
+
+ enable_chkfs
+
+ mount_ubifs $DEV $MNT "noauthentication" "noatime"
+ res=$?
+ if [[ $res != 0 ]]
+ then
+ fatal "mount fail $res"
+ fi
+
+ if [[ "$encryption" != "encrypted" ]]; then
+ # Check filesystem information, skip encrypted image.
+ # fscryptctl is not compatible with fscryptctl in mtd-utils.
+ # See https://github.com/google/fscryptctl/issues/33
+ du -sh $MNT > /dev/null # Make sure all files are accessible
+ ret=$?
+ if [[ $ret != 0 ]]; then
+ fatal "Cannot access all files"
+ fi
+
+ parse_dir "md5sum"
+ fi
+
+ check_err_msg
+
+ umount $MNT
+ res=$?
+ if [[ $res != 0 ]]
+ then
+ fatal "unmount fail $res"
+ fi
+
+ check_err_msg
+ disable_chkfs
+
+ if [[ "$test_medium" != "volume" ]]; then
+ rm -f $IMG_FILE
+ fi
+ modprobe -r ubifs
+ modprobe -r ubi
+ modprobe -r $simulator
+
+ echo "----------------------------------------------------------------------"
+}
+
+check_fsstress
+start_t=$(date +%s)
+echo "Do mkfs+fsck+mount test in kinds of flashes"
+mount -t tmpfs -osize=50m none $TMP_MNT || fatal "cannot mount tmpfs"
+echo 123 > $TMP_MNT/file
+setfattr -n user.xyz -v 123abc $TMP_MNT/file
+fsstress -d $TMP_MNT -l30 -n10 -p4
+# Record filesystem information
+rm -f $TMP_FILE 2>/dev/null
+read_dir $TMP_MNT "md5sum"
+
+# No authentication tests, which needs a specific key from certs directory corresponding to linux source code..
+# See https://patchwork.ozlabs.org/project/linux-mtd/cover/20190806104928.1224-1-s.hauer@pengutronix.de/
+for simulator in "mtdram" "nandsim"; do
+ for encryption in "encrypted" "noencrypted"; do
+ for test_medium in "volume" "file"; do
+ for space_fix in "fix_space" "nofix_space"; do
+ for need_fsck in "do_fsck" "no_fsck"; do
+ for double_mkfs in "double_format" "format_once"; do
+ run_test "$simulator" "64" "64" "2048" $encryption $test_medium $space_fix $need_fsck $double_mkfs
+ run_test "$simulator" "128" "128" "2048" $encryption $test_medium $space_fix $need_fsck $double_mkfs
+ run_test "$simulator" "512" "512" "2048" $encryption $test_medium $space_fix $need_fsck $double_mkfs
+ run_test "$simulator" "1024" "512" "2048" $encryption $test_medium $space_fix $need_fsck $double_mkfs
+ done
+ done
+ done
+ done
+ done
+done
+
+umount $TMP_MNT
+rm -f $TMP_FILE 2>/dev/null
+end_t=$(date +%s)
+time_cost=$(( end_t - start_t ))
+echo "Success, cost $time_cost seconds"
+exit 0
diff --git a/tests/ubifs_tools-tests/ubifs_tools_run_all.sh.in b/tests/ubifs_tools-tests/ubifs_tools_run_all.sh.in
new file mode 100755
index 0000000..a7caad0
--- /dev/null
+++ b/tests/ubifs_tools-tests/ubifs_tools_run_all.sh.in
@@ -0,0 +1,65 @@
+#!/bin/sh
+# Copyright (c), 2024, Huawei Technologies Co, Ltd.
+# Author: Zhihao Cheng <chengzhihao1@huawei.com>
+#
+# Test Description:
+# Run all testcases under 'tests' directory
+
+function print_line()
+{
+ echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
+ echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
+}
+
+TESTBINDIR=@TESTBINDIR@
+
+print_line
+$TESTBINDIR/authentication_refuse.sh
+if [[ $? != 0 ]]; then
+ echo "authentication_refuse failed"
+ exit 1
+fi
+print_line
+$TESTBINDIR/powercut_fsck_mount.sh
+if [[ $? != 0 ]]; then
+ echo "powercut_fsck_mount failed"
+ exit 1
+fi
+print_line
+$TESTBINDIR/cycle_corrupted_fsck_fault_inject.sh
+if [[ $? != 0 ]]; then
+ echo "cycle_corrupted_fsck_fault_inject failed"
+ exit 1
+fi
+print_line
+$TESTBINDIR/fsck_bad_image.sh
+if [[ $? != 0 ]]; then
+ echo "fsck_bad_image failed"
+ exit 1
+fi
+print_line
+$TESTBINDIR/random_corrupted_fsck.sh
+if [[ $? != 0 ]]; then
+ echo "random_corrupted_fsck failed"
+ exit 1
+fi
+print_line
+$TESTBINDIR/cycle_powercut_mount_fsck.sh
+if [[ $? != 0 ]]; then
+ echo "cycle_powercut_mount_fsck failed"
+ exit 1
+fi
+print_line
+$TESTBINDIR/cycle_mount_fsck_check.sh
+if [[ $? != 0 ]]; then
+ echo "cycle_mount_fsck_check failed"
+ exit 1
+fi
+print_line
+$TESTBINDIR/build_fs_from_dir.sh
+if [[ $? != 0 ]]; then
+ echo "build_fs_from_dir failed"
+ exit 1
+fi
+
+exit 0