diff --git a/src/esp_littlefs.c b/src/esp_littlefs.c index f66c018..73c28af 100644 --- a/src/esp_littlefs.c +++ b/src/esp_littlefs.c @@ -896,6 +896,22 @@ static int vfs_littlefs_open(void* ctx, const char * path, int flags, int mode) return LFS_ERR_INVAL; } + /* Sync after opening. If we are overwriting a file, this will free that + * file's blocks in storage, prevent OOS errors. + * See TEST_CASE: + * "Rewriting file frees space immediately (#7426)" + */ + res = lfs_file_sync(efs->fs, &file->file); + if(res < 0){ + errno = -res; +#ifndef CONFIG_LITTLEFS_USE_ONLY_HASH + ESP_LOGV(TAG, "Failed to sync at opening file \"%s\". Error %s (%d)", + file->path, esp_littlefs_errno(res), res); +#else + ESP_LOGV(TAG, "Failed to sync at opening file %d. Error %d", fd, res); +#endif + } + file->hash = compute_hash(path); #ifndef CONFIG_LITTLEFS_USE_ONLY_HASH memcpy(file->path, path, path_len); diff --git a/src/test/test_littlefs.c b/src/test/test_littlefs.c index 7c78a3f..0f0043a 100644 --- a/src/test/test_littlefs.c +++ b/src/test/test_littlefs.c @@ -972,7 +972,37 @@ TEST_CASE("SPIFFS COMPAT", "[littlefs]") } #endif // CONFIG_LITTLEFS_SPIFFS_COMPAT +TEST_CASE("Rewriting file frees space immediately (#7426)", "[littlefs]") +{ + /* modified from: + * https://github.com/esp8266/Arduino/commit/c663c55926f205723c3d56dd7030bacbe7960f8e + */ + + test_setup(); + + size_t total = 0, used = 0; + TEST_ESP_OK(esp_littlefs_info(littlefs_test_partition_label, &total, &used)); + + // 2 block overhead + int kb_to_write = (total - used - (2*4096)) / 1024; + + // Create and overwrite a file >50% of spaceA (48/64K) + uint8_t buf[1024]; + memset(buf, 0xaa, 1024); + for (uint8_t x = 0; x < 2; x++) { + FILE *f = fopen(littlefs_base_path "/file1.bin", "w"); + TEST_ASSERT_NOT_NULL(f); + + for (size_t i = 0; i < kb_to_write; i++) { + TEST_ASSERT_EQUAL_INT(1024, fwrite(buf, 1, 1024, f)); + } + fclose(f); + } + test_teardown(); +} + static void test_setup() { + esp_littlefs_format(littlefs_test_partition_label); const esp_vfs_littlefs_conf_t conf = { .base_path = littlefs_base_path, .partition_label = littlefs_test_partition_label,