Description
During internal functional stress tests with Zephyr OS using SLC NAND flash, I encountered an issue. The main process involves repeatedly deleting, renaming, and writing files. Eventually, an assertion failure occurs during the file deletion process. Specifically, the assertion is triggered when gstate.tag is 0 and orphans is -1. The assertion failure occurs at the Heading code section. As follows:
if (lfs_tag_type3(tag) == LFS_TYPE_DIR) {
// fix orphan
### err = lfs_fs_preporphans(lfs, -1);
if (err) {
return err;
}
err = lfs_fs_pred(lfs, dir.m.pair, &cwd);
if (err) {
return err;
}
err = lfs_dir_drop(lfs, &cwd, &dir.m);
if (err) {
return err;
}
}
#ifndef LFS_READONLY
static int lfs_fs_preporphans(lfs_t *lfs, int8_t orphans) {
### LFS_ASSERT(lfs_tag_size(lfs->gstate.tag) > 0x000 || orphans >= 0);
LFS_ASSERT(lfs_tag_size(lfs->gstate.tag) < 0x1ff || orphans <= 0);
lfs->gstate.tag += orphans;
lfs->gstate.tag = ((lfs->gstate.tag & ~LFS_MKTAG(0x800, 0, 0)) |
((uint32_t)lfs_gstate_hasorphans(&lfs->gstate) << 31));
return 0;
}
#endif
Process diagram:
lfs_rawremove()
|__ lfs_fs_preporphans(lfs, +1)
|__ lfs_dir_commit() <-- commit delete tag
| |__ lfs_fs_deorphan()
| |__ lfs_fs_preporphans(lfs, -lfs_gstate_getorphans(&lfs->gstate)) <--- Set gstate.tag to 0
|__ lfs_fs_preporphans(lfs, -1) <--- Caught an assertion, expecting gstate.tag to be > 0
littlefs version: v2.8
Our team has added debug logs for verification. During the deletion process, a tag commit is required, which triggers two levels of metadata block relocation. Normally, without relocation, gstate.tag would be incremented by 1 before the commit and decremented by 1 after the commit.
However, after two levels of relocation, there is a segment in the flow post-relocation that resets gstate.tag to zero. Consequently, when the deletion process attempts to decrement gstate.tag by 1 after the final commit, it encounters an assertion failure.
I would like to ask for some advice.
What could be the possible causes of the described issue?
What is the specific purpose of the implementation in lfs_fs_preporphans?