littlefs
littlefs copied to clipboard
HardFault on lfs_file_close() after upgrade to v2.5.0
I upgraded littlefs to v2.5.0 and I now encounter a HardFault when trying to close a file.
my function call sequence is :
- lfs_file_opencfg()
- write X data blocks
- lfs_file_seek()
- lfs_file_write()
- write X data blocks
- lfs_file_close()
call stack:
The failed line:
variable values:
The data address is invalid for my system it is 0x4e000000.
This worked for me before updating to v2.5.0 although I used it a bit differently with lfs_file_open() instead of lfs_file_opencfg().
Any idea what's going on ?
Probably worth enabling the LFS_ASSERT macro to see where your fault could be. Also are you setting a value in the lfs_config for the new metadata_max parameter?
LFS_ASSERT was enabled in the original post ( I made sure it triggers on false config ). It doesn't trigger. I am not setting metadata_max .
Is it possible you're running out of memory and malloc is giving you an address past RAM?
0x4e000000 certainly looks like an address, but if it's not an address it would be a weird value to see in a buffer overrun.
littlefs is compiled with LFS_NO_MALLOC so malloc shouldn't be used.
0x4e000000 is a reserved address for my MCU ( https://pdfserv.maximintegrated.com/en/an/ug6766.pdf - page 33 )
The wrong buffer address is coming for lfs_dir_traverse() :
Is there any thing I can check that will help debug this problem ?
Can you show your buffer definition and the call to lfs_file_opencfg?
int do_fs_lfs_file_open(do_fs_lfs_file_handler_s *file_handler, do_lfs_file_system_e fs, const char *path, bool append)
{
int ret, flags;
struct lfs_file_config cfg = {.attr_count = 0, .attrs = 0, .buffer = do_fs_lfs_cache_buffer};
// close any open file
do_fs_lfs_file_close(file_handler);
file_handler->lfs = do_fs_lfs_get_file_system(fs);
file_handler->append = append;
if (file_handler->append)
{
flags = LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND;
}
else
{
flags = LFS_O_WRONLY | LFS_O_CREAT;
}
ret = lfs_file_opencfg(file_handler->lfs, &(file_handler->file), path, flags, &cfg);
return ret;
}
as a global variable :
static uint8_t do_fs_lfs_cache_buffer[DO_FS_LFS_CACHE_SIZE] __attribute__((aligned(4)));
Hmmm, I'm not sure it's related but I think the entire struct lfs_file_config
needs to be static or global as it's content doesn't get copied. I can see some scenarios where this would cause the wrong operation
The usage says this:
The config struct must be allocated while the file is open, and the config struct must be zeroed for defaults and backwards compatibility
@Xenoamor Thank you !
This fixes my HardFault.
To me it is not 100% clear from the usage that this struct has to be allocated statically/globally .
To me it is not 100% clear from the usage that this struct has to be allocated statically/globally .
This is something I want to move away from eventually. The small RAM savings in certain circumstances does not outweigh the unintuitiveness. But on its own it's not worth a breaking change to the APIs. So it will probably stay how it is until there are other breaking API changes.
I've been investigating the same hardfault today, but under slightly different circumstances. In my case, I'd accidentally called lfs_file_close()
without first opening a file. This bit was my fault, however there probably should be some additional checking here - the hardfault was ultimately being caused because file->cfg
was NULL.
lfs_file_rawsync()
calls lfs_dir_commit()
with two tags - the first of which will be OK, but the second is derived from file->cfg->attr_count
and file->cfg->attrs
, both of which are undefined. This false tag is eventually passed to lfs_dir_traverse()
, and fails on line 948 because a[i] points to somewhere invalid.
I'm not sure of the correct way to fix this - I'll leave that up to people who know the source code a bit better than I do... but thought this would help if anyone else has been chasing the same problem.
Is this not caught if you use LFS_ASSERT? Fairly sure it checks the API usage and that the file is open, it's usually worth using this in your debug builds