LittleFS unexpected behaviour · Issue #7426 · esp8266/Arduino (original) (raw)
Basic Infos
- This issue complies with the issue POLICY doc.
- I have read the documentation at readthedocs and the issue is not addressed there.
- I have tested that the issue is present in current master branch (aka latest git).
- I have searched the issue tracker for a similar issue.
Platform
- Hardware: [ESP-12]
- Core Version: [2.7.1]
- Development Env: [Arduino IDE]
- Operating System: [Ubuntu]
Settings in IDE
- Module: [Generic ESP8266 Module]
- FS Size [1 MB]
Problem Description
When working with big files on LittleFS, overwriting a big file might fail as LittleFS seems to release the previous file contents only after a sync (i.e. close) of that file as it uses a COW strategy (see littlefs-project/littlefs#123)
So if you have a 1MB FS and a file of 512KB you cannot overwrite that file with 512KB of data. This will fail since during that overwrite up to 1024KB need to be in that 1M FS which has less net space.
Remedy: you have to truncate the file by
- open(file, "w")
- close() it
- re-open it open(file, "w")
This should be somehow documented in the docs. It would also be nice to have a call likeLittleFS.sync();
or another flag LittleFS.open(... "ws")
to indicate that writing should be synced. The lower lfs_* calls seem to provide such functionality.
MCVE Sketch
#include <LittleFS.h> #define BAUDRATE 74880
uint16_t listDir(String indent, String path) { uint16_t dirCount = 0; Dir dir = LittleFS.openDir(path); while (dir.next()) { ++dirCount; if (dir.isDirectory()) { Serial.printf_P(PSTR("%s%s [Dir]\n"), indent.c_str(), dir.fileName().c_str()); dirCount += listDir(indent + " ", path + dir.fileName() + "/"); } else Serial.printf_P(PSTR("%s%-16s (%ld Bytes)\n"), indent.c_str(), dir.fileName().c_str(), (uint32_t)dir.fileSize()); } return dirCount; }
void create_file(String path, uint32_t fsize) { File f = LittleFS.open(path, "w"); char buf[536]; // whatever for (auto i = 0; i < fsize; ) { auto n = fsize - i; if (n > sizeof(buf)) n = sizeof(buf); auto nw = f.write(buf, n); if (nw != n) Serial.printf_P(PSTR("\n\nBug at position %u: expected %d written, got %d written...\n"), i, n, nw); i += nw; if (0 == nw) break; } f.close(); }
void setup(void) { Serial.begin(BAUDRATE); Serial.printf_P(PSTR("FS init: %s\n"), LittleFS.begin() ? PSTR("ok") : PSTR("fail!")); LittleFS.format();
listDir("", "/");
uint32_t maxL = 768 * 1024;
Serial.printf_P(PSTR("Create /a.bin with size %u..."), maxL); uint32_t startTime = millis(); create_file("/a.bin", maxL); Serial.printf_P(PSTR(" took %lu ms!\n"), millis() - startTime);
listDir("", "/");
maxL += 1024; Serial.printf_P(PSTR("Overwriting /a.bin with size %d..."), maxL);
startTime = millis(); create_file("/a.bin", maxL); Serial.printf_P(PSTR(" took %lu ms!\n"), millis() - startTime);
listDir("", "/"); }
void loop() {}
Debug Messages
ets Jan 8 2013,rst cause:2, boot mode:(3,6)
load 0x4010f000, len 3456, room 16
tail 0
chksum 0x84
csum 0x84
va5432625
~ld
FS init: ok
Create /a.bin with size 786432... took 15225 ms!
a.bin (786432 Bytes)
Overwriting /a.bin with size 787456...
Bug at position 212792: expected 536 written, got 0 written...
took 4063 ms!
a.bin (786432 Bytes)