Merge branch 'feature/add_esp_spiffs_check' into 'master'

spiffs: Add esp_spiffs_check() function

See merge request espressif/esp-idf!15565
pull/8779/head
Martin Vychodil 2022-04-10 07:52:47 +08:00
commit d8f64961af
7 zmienionych plików z 74 dodań i 2 usunięć

Wyświetl plik

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -48,6 +48,7 @@ typedef struct {
char path[SPIFFS_OBJ_NAME_LEN]; /*!< Requested directory name */
} vfs_spiffs_dir_t;
static int spiffs_res_to_errno(s32_t fr);
static int vfs_spiffs_open(void* ctx, const char * path, int flags, int mode);
static ssize_t vfs_spiffs_write(void* ctx, int fd, const void * data, size_t size);
static ssize_t vfs_spiffs_read(void* ctx, int fd, void * dst, size_t size);
@ -305,6 +306,22 @@ esp_err_t esp_spiffs_info(const char* partition_label, size_t *total_bytes, size
return ESP_OK;
}
esp_err_t esp_spiffs_check(const char* partition_label)
{
int index;
if (esp_spiffs_by_label(partition_label, &index) != ESP_OK) {
return ESP_ERR_INVALID_STATE;
}
if (SPIFFS_check(_efs[index]->fs) != SPIFFS_OK) {
int spiffs_res = SPIFFS_errno(_efs[index]->fs);
ESP_LOGE(TAG, "SPIFFS_check failed (%d)", spiffs_res);
errno = spiffs_res_to_errno(SPIFFS_errno(_efs[index]->fs));
SPIFFS_clearerr(_efs[index]->fs);
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t esp_spiffs_format(const char* partition_label)
{
bool partition_was_mounted = false;

Wyświetl plik

@ -84,6 +84,17 @@ esp_err_t esp_spiffs_format(const char* partition_label);
*/
esp_err_t esp_spiffs_info(const char* partition_label, size_t *total_bytes, size_t *used_bytes);
/**
* Check integrity of SPIFFS
*
* @param partition_label Same label as passed to esp_vfs_spiffs_register
* @return
* - ESP_OK if successful
* - ESP_ERR_INVALID_STATE if not mounted
* - ESP_FAIL on error
*/
esp_err_t esp_spiffs_check(const char* partition_label);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -17,6 +17,7 @@ Notes
- SPIFFS is able to reliably utilize only around 75% of assigned partition space.
- When the filesystem is running out of space, the garbage collector is trying to find free space by scanning the filesystem multiple times, which can take up to several seconds per write function call, depending on required space. This is caused by the SPIFFS design and the issue has been reported multiple times (e.g. `here <https://github.com/espressif/esp-idf/issues/1737>`_) and in the official `SPIFFS github repository <https://github.com/pellepl/spiffs/issues/>`_. The issue can be partially mitigated by the `SPIFFS configuration <https://github.com/pellepl/spiffs/wiki/Configure-spiffs>`_.
- Deleting a file does not always remove the whole file, which leaves unusable sections throughout the filesystem.
- When ESP32 experiences a power loss during a file system operation it could result in SPIFFS corruption. However the file system still might be recovered via ``esp_spiffs_check`` function. More details in the official SPIFFS `FAQ <https://github.com/pellepl/spiffs/wiki/FAQ>`.
Tools
-----

Wyświetl plik

@ -17,6 +17,7 @@ SPIFFS 是一个用于 SPI NOR flash 设备的嵌入式文件系统,支持磨
- SPIFFS 只能稳定地使用约 75% 的指定分区容量。
- 当文件系统空间不足时,垃圾收集器会尝试多次扫描文件系统来寻找可用空间。根据所需空间的不同,写操作会被调用多次,每次函数调用将花费几秒。同一操作可能会花费不同时长的问题缘于 SPIFFS 的设计,且已在官方的 `SPIFFS github 仓库 <https://github.com/pellepl/spiffs/issues/>`_ 或是 <https://github.com/espressif/esp-idf/issues/1737>`_ 中被多次报告。这个问题可以通过 `SPIFFS 配置 <https://github.com/pellepl/spiffs/wiki/Configure-spiffs>`_ 部分缓解。
- 被删除文件通常不会被完全清除,会在文件系统中遗留下无法使用的部分。
- 如果 ESP32 在文件系统操作期间断电,可能会导致 SPIFFS 损坏。但是仍可通过 ``esp_spiffs_check`` 函数恢复文件系统。详情请参阅官方 SPIFFS `FAQ <https://github.com/pellepl/spiffs/wiki/FAQ>`
工具
-----

Wyświetl plik

@ -20,6 +20,11 @@ SPIFFS partition size is set in partitions_example.csv file. See [Partition Tabl
This example does not require any special hardware, and can be run on any common development board.
### Configure the project
* Open the project configuration menu (`idf.py menuconfig`)
* Configure SPIFFS settings under "SPIFFS Example menu". See note about `esp_spiffs_check` function on [SPIFFS Filesystem](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/storage/spiffs.html) page.
### Build and flash
Replace PORT with serial port name:

Wyświetl plik

@ -0,0 +1,9 @@
menu "SPIFFS Example menu"
config EXAMPLE_SPIFFS_CHECK_ON_START
bool "Run SPIFFS_check on every start-up"
default y
help
If this config item is set, esp_spiffs_check() will be run on every start-up.
Slow on large flash sizes.
endmenu

Wyświetl plik

@ -42,14 +42,42 @@ void app_main(void)
return;
}
#ifdef CONFIG_EXAMPLE_SPIFFS_CHECK_ON_START
ESP_LOGI(TAG, "Performing SPIFFS_check().");
ret = esp_spiffs_check(conf.partition_label);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "SPIFFS_check() failed (%s)", esp_err_to_name(ret));
return;
} else {
ESP_LOGI(TAG, "SPIFFS_check() successful");
}
#endif
size_t total = 0, used = 0;
ret = esp_spiffs_info(conf.partition_label, &total, &used);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s)", esp_err_to_name(ret));
ESP_LOGE(TAG, "Failed to get SPIFFS partition information (%s). Formatting...", esp_err_to_name(ret));
esp_spiffs_format(conf.partition_label);
return;
} else {
ESP_LOGI(TAG, "Partition size: total: %d, used: %d", total, used);
}
#
// Check consistency of reported partiton size info.
if (used > total) {
ESP_LOGW(TAG, "Number of used bytes cannot be larger than total. Performing SPIFFS_check().");
ret = esp_spiffs_check(conf.partition_label);
// Could be also used to mend broken files, to clean unreferenced pages, etc.
// More info at https://github.com/pellepl/spiffs/wiki/FAQ#powerlosses-contd-when-should-i-run-spiffs_check
if (ret != ESP_OK) {
ESP_LOGE(TAG, "SPIFFS_check() failed (%s)", esp_err_to_name(ret));
return;
} else {
ESP_LOGI(TAG, "SPIFFS_check() successful");
}
}
// Use POSIX and C standard library functions to work with files.
// First create a file.
ESP_LOGI(TAG, "Opening file");