littlefs: Fixed issue with cleanup in mount function on error

As a part of the v1.6 update, littlefs added proper handling for
cleaning up memory in the case of an error during mount. This took care
of a memory leak users were seeing. Ironically, it turns out the implementation
and user patterns in mbed-os was _relying_ on this memory leak to avoid a
double free in the same case of an error during mount.

The issue was that a failed mount would leave the LittleFileSystem class in a
state where it thought it was mounted, and later it would attempt to
unmount the filesystem. With the previous memory leak this would be
"ok", and the leaked memory would be freed. But with the fix in v1.6,
no memory is leaked, and the incorrect free triggers a hard fault.

Fixed to clean up state properly on failed mounts.
pull/7851/head
Christopher Haster 2018-08-21 17:23:32 -05:00
parent b53a9ea4c0
commit cc1bad90a7
1 changed files with 17 additions and 12 deletions

View File

@ -134,6 +134,7 @@ int LittleFileSystem::mount(BlockDevice *bd)
_bd = bd; _bd = bd;
int err = _bd->init(); int err = _bd->init();
if (err) { if (err) {
_bd = NULL;
LFS_INFO("mount -> %d", err); LFS_INFO("mount -> %d", err);
_mutex.unlock(); _mutex.unlock();
return err; return err;
@ -164,36 +165,40 @@ int LittleFileSystem::mount(BlockDevice *bd)
} }
err = lfs_mount(&_lfs, &_config); err = lfs_mount(&_lfs, &_config);
LFS_INFO("mount -> %d", lfs_toerror(err)); if (err) {
_bd = NULL;
LFS_INFO("mount -> %d", lfs_toerror(err));
_mutex.unlock();
return lfs_toerror(err);
}
_mutex.unlock(); _mutex.unlock();
return lfs_toerror(err); LFS_INFO("mount -> %d", 0);
return 0;
} }
int LittleFileSystem::unmount() int LittleFileSystem::unmount()
{ {
_mutex.lock(); _mutex.lock();
LFS_INFO("unmount(%s)", ""); LFS_INFO("unmount(%s)", "");
int res = 0;
if (_bd) { if (_bd) {
int err = lfs_unmount(&_lfs); int err = lfs_unmount(&_lfs);
if (err) { if (err && !res) {
LFS_INFO("unmount -> %d", lfs_toerror(err)); res = lfs_toerror(err);
_mutex.unlock();
return lfs_toerror(err);
} }
err = _bd->deinit(); err = _bd->deinit();
if (err) { if (err && !res) {
LFS_INFO("unmount -> %d", err); res = err;
_mutex.unlock();
return err;
} }
_bd = NULL; _bd = NULL;
} }
LFS_INFO("unmount -> %d", 0); LFS_INFO("unmount -> %d", res);
_mutex.unlock(); _mutex.unlock();
return 0; return res;
} }
int LittleFileSystem::format(BlockDevice *bd, int LittleFileSystem::format(BlockDevice *bd,