From 5e7c0976fa8516f97fa361a1f3758e143a4c133c Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 27 Dec 2017 13:53:35 -0600 Subject: [PATCH] littlefs: Fixed issue with immediate exhaustion and small unaligned storage This was a small hole in the logic that handles initializing the lookahead buffer. To imitate exhaustion (so the block allocator will trigger a scan), the lookahead buffer is rewound a full lookahead and set up to look like it is exhausted. However, unlike normal allocation, this rewind was not kept aligned to a multiple of the scan size, which is limited by both the lookahead buffer and the total storage size. This bug went unnoticed for so long because it only causes problems when the block device is both: 1. Not aligned to the lookahead buffer (not a power of 2) 2. Smaller than the lookahead buffer While this seems like a strange corner case for a block device, this turned out to be very common for internal flash, especially when a handleful of blocks are reserved for code. --- .travis.yml | 9 ++++----- features/filesystem/littlefs/littlefs/.travis.yml | 7 +++---- features/filesystem/littlefs/littlefs/lfs.c | 6 +++--- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/.travis.yml b/.travis.yml index a03c3af692..71721fb6fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -142,11 +142,10 @@ matrix: # Run local littlefs tests - CFLAGS="-Wno-format" make -C$LITTLEFS/littlefs test QUIET=1 # Run local littlefs tests with set of variations - - CFLAGS="-Wno-format -DLFS_READ_SIZE=64 -DLFS_PROG_SIZE=64" make -C$LITTLEFS/littlefs test QUIET=1 - - CFLAGS="-Wno-format -DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" make -C$LITTLEFS/littlefs test QUIET=1 - - CFLAGS="-Wno-format -DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512" make -C$LITTLEFS/littlefs test QUIET=1 - - CFLAGS="-Wno-format -DLFS_BLOCK_COUNT=1023" make -C$LITTLEFS/littlefs test QUIET=1 - - CFLAGS="-Wno-format -DLFS_LOOKAHEAD=2048" make -C$LITTLEFS/littlefs test QUIET=1 + - CFLAGS="-Wno-format -DLFS_READ_SIZE=64 -DLFS_PROG_SIZE=64" make -C$LITTLEFS/littlefs test QUIET=1 + - CFLAGS="-Wno-format -DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" make -C$LITTLEFS/littlefs test QUIET=1 + - CFLAGS="-Wno-format -DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512" make -C$LITTLEFS/littlefs test QUIET=1 + - CFLAGS="-Wno-format -DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD=2048" make -C$LITTLEFS/littlefs test QUIET=1 # Self-hosting littlefs fuzz test with littlefs-fuse - make -Clittlefs_fuse - littlefs_fuse/lfs --format /dev/loop0 diff --git a/features/filesystem/littlefs/littlefs/.travis.yml b/features/filesystem/littlefs/littlefs/.travis.yml index d673c159ab..c17af8b17b 100644 --- a/features/filesystem/littlefs/littlefs/.travis.yml +++ b/features/filesystem/littlefs/littlefs/.travis.yml @@ -12,10 +12,9 @@ script: - make test QUIET=1 # run tests with a few different configurations - - CFLAGS="-DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" make test QUIET=1 - - CFLAGS="-DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512" make test QUIET=1 - - CFLAGS="-DLFS_BLOCK_COUNT=1023" make test QUIET=1 - - CFLAGS="-DLFS_LOOKAHEAD=2048" make test QUIET=1 + - CFLAGS="-DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" make test QUIET=1 + - CFLAGS="-DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512" make test QUIET=1 + - CFLAGS="-DLFS_BLOCK_COUNT=1023 -DLFS_LOOKAHEAD=2048" make test QUIET=1 # self-host with littlefs-fuse for fuzz test - make -C littlefs-fuse diff --git a/features/filesystem/littlefs/littlefs/lfs.c b/features/filesystem/littlefs/littlefs/lfs.c index 04870925cd..4bd834d950 100644 --- a/features/filesystem/littlefs/littlefs/lfs.c +++ b/features/filesystem/littlefs/littlefs/lfs.c @@ -2039,9 +2039,9 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { return err; } - // setup free lookahead - lfs->free.begin = -lfs->cfg->lookahead; - lfs->free.off = lfs->cfg->lookahead; + // setup free lookahead, rewind so first allocation triggers a scan + lfs->free.begin = -lfs_min(lfs->cfg->lookahead, lfs->cfg->block_count); + lfs->free.off = -lfs->free.begin; lfs->free.end = lfs->free.begin + lfs->free.off + lfs->cfg->block_count; // load superblock