Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File system corruption when creating directories #979

Closed
josesimoes opened this issue May 9, 2024 · 2 comments
Closed

File system corruption when creating directories #979

josesimoes opened this issue May 9, 2024 · 2 comments
Labels
needs investigation no idea what is wrong

Comments

@josesimoes
Copy link

This is kind of a follow-up on #973.

Take the following code, following a successful call to lfs_format() followed by lfs_mount().

(please ignore the file system var which is coming from the rest of the test code)

char *filePath = "temp/testdir/file1.txt";
char *dir1Path = "temp";
char *dir2Path = "temp/testdir";
volatile int32_t result;
struct lfs_info info;

// check file path
result = lfs_stat(&lfs[index], filePath, &info);

// try to get file attributes
result = lfs_getattr(
        &lfs[index],
        (const char *)filePath,
        NANO_LITTLEFS_ATTRIBUTE,
        &attributes,
        NANO_LITTLEFS_ATTRIBUTE_SIZE);

// create directories in the path
result = lfs_mkdir(&lfs[index], dir1Path);
result = lfs_mkdir(&lfs[index], dir2Path);

All the above calls return successfully with LFS_ERR_OK.
Now comes the unexpected situation.

Following the above, any of these calls fail with LFS_ERR_CORRUPT.

// check directory exists
result = lfs_stat(&lfs[index], dir2Path, &info);

// check file path
result = lfs_stat(&lfs[index], filePath, &info);

Restarting the application (which detects the corruption on the 1st call to lfs_mount() which requires subsequent calls to lfs_format() followed by lfs_mount() and will execute the initial code again with LFS_ERR_OK.

Interestingly, if instead of calling lfs_stat() the following code is executed, everything runs smootly.

// set file attributes
// hardcoded to 128 which is value for FileAttributes_Normal
nanoAttributes = 128;
attr = (struct lfs_attr){
    .type = NANO_LITTLEFS_ATTRIBUTE,
    .size = NANO_LITTLEFS_ATTRIBUTE_SIZE,
    .buffer = &nanoAttributes
};
 
fileConfig = (struct lfs_file_config) {
    .buffer = NULL,
    .attrs = &attr,
    .attr_count = 1,
};

// create file
result =  lfs_file_opencfg(&lfs[index], &file, filePath,  LFS_O_CREAT | LFS_O_RDWR, &fileConfig);

 // sync file to save attributes
result = lfs_file_sync(&lfs[index], &file);

// read file attributes
result = lfs_getattr(
        &lfs[index],
        (const char *)filePath,
        NANO_LITTLEFS_ATTRIBUTE,
        &attributes,
        NANO_LITTLEFS_ATTRIBUTE_SIZE);

// close file
result = lfs_file_close(&lfs[index], &file);

// check file existance
result = lfs_stat(&lfs[index], filePath, &info);

// read file attributes
result = lfs_getattr(
        &lfs[index],
        (const char *)filePath,
        NANO_LITTLEFS_ATTRIBUTE,
        &attributes,
        NANO_LITTLEFS_ATTRIBUTE_SIZE);

I'm I missing something after the directory creation that can "force" any sync or similar? Or is the call to lfs_stat() somehow disrrupting the file system cache/integrity?

@geky-bot geky-bot added needs investigation no idea what is wrong and removed needs investigation no idea what is wrong labels May 10, 2024
@geky geky added the needs investigation no idea what is wrong label May 10, 2024
@geky
Copy link
Member

geky commented May 10, 2024

Hi @josesimoes, hmm, I have not seen something like this before.

A couple questions to try to understand the context:

  • Does this code work without using attributes? That would narrow things down.

  • Is there anything logged by littlefs's LFS_DEBUG/LFS_WARN statements? Especially related to gstate.

  • Does this occur after a power-loss? It sounds easily reproducible so I'm guessing no?

// set file attributes
// hardcoded to 128 which is value for FileAttributes_Normal
nanoAttributes = 128;
attr = (struct lfs_attr){
    .type = NANO_LITTLEFS_ATTRIBUTE,
    .size = NANO_LITTLEFS_ATTRIBUTE_SIZE,
    .buffer = &nanoAttributes
};

This is a bit confusing. Maybe I am missing something, how exactly is nanoAttributes declared? Is it a uint8_t array of size 128?

Just for completeness, what is the value of NANO_LITTLEFS_ATTRIBUTE and NANO_LITTLEFS_ATTRIBUTE_SIZE? NANO_LITTLEFS_ATTRIBUTE_SIZE should be the same size as the buffer array.

I'm I missing something after the directory creation that can "force" any sync or similar? Or is the call to lfs_stat() somehow disrrupting the file system cache/integrity?

There is a special "force consistency" step that occurs on the first mutation after lfs_mount. This occurs lazily so read-only mounts of littlefs are guaranteed not to write to disk.

You can trigger this explicitly with lfs_fs_mkconsistent.

It would be interesting to know if calling lfs_fs_mkconsistent before lfs_getattr prevents the behavior you are seeing, though if there is no power-loss (or version upgrade?) I think this would be unlikely.

@josesimoes
Copy link
Author

Just to close this issue, a quick follow-up: this ended being an issue in the driver. It was using the wrong command to erase the block. Great support from @geky! Definitely recommend it. 💯 👍🏻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs investigation no idea what is wrong
Projects
None yet
Development

No branches or pull requests

3 participants