mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-01 18:50:34 +03:00
fix(storage/fatfs): Fix usage of rootdir parameter in FatFS mounting API (WL version)
Deployment of the root directory count parameter was wrong for FAT12/16 formatting (WL version). This fix resolves the issue and allows application of any number of rootdir entries within appropriate limits.
This commit is contained in:
@@ -111,6 +111,12 @@ typedef struct {
|
||||
* may be different.
|
||||
*/
|
||||
bool use_one_fat;
|
||||
/**
|
||||
* Number of reserved root directory items.
|
||||
* Effective only on FAT12/16, ignored on other file systems (by FatFS lib).
|
||||
* 0 == default (maximum number of 32B entries given by the sector size).
|
||||
*/
|
||||
size_t rootdir_entries;
|
||||
} esp_vfs_fat_mount_config_t;
|
||||
|
||||
#define VFS_FAT_MOUNT_DEFAULT_CONFIG() \
|
||||
@@ -120,6 +126,7 @@ typedef struct {
|
||||
.allocation_unit_size = 0, \
|
||||
.disk_status_check_enable = false, \
|
||||
.use_one_fat = false, \
|
||||
.rootdir_entries = 0, \
|
||||
}
|
||||
|
||||
// Compatibility definition
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -78,7 +78,7 @@ vfs_fat_spiflash_ctx_t* get_vfs_fat_spiflash_ctx(wl_handle_t wlhandle)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static esp_err_t s_f_mount_rw(FATFS *fs, const char *drv, const esp_vfs_fat_mount_config_t *mount_config, vfs_fat_x_ctx_flags_t *out_flags, size_t sec_num)
|
||||
static esp_err_t s_f_mount_rw(FATFS *fs, const char *drv, const esp_vfs_fat_mount_config_t *mount_config, vfs_fat_x_ctx_flags_t *out_flags)
|
||||
{
|
||||
FRESULT fresult = f_mount(fs, drv, 1);
|
||||
if (fresult != FR_OK) {
|
||||
@@ -97,13 +97,12 @@ static esp_err_t s_f_mount_rw(FATFS *fs, const char *drv, const esp_vfs_fat_moun
|
||||
|
||||
size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(CONFIG_WL_SECTOR_SIZE, mount_config->allocation_unit_size);
|
||||
ESP_LOGI(TAG, "Formatting FATFS partition, allocation unit size=%d", alloc_unit_size);
|
||||
UINT root_dir_entries;
|
||||
if (CONFIG_WL_SECTOR_SIZE == 512) {
|
||||
root_dir_entries = 16;
|
||||
} else {
|
||||
root_dir_entries = 128;
|
||||
UINT root_dir_entries = mount_config->rootdir_entries;
|
||||
if (root_dir_entries == 0) {
|
||||
root_dir_entries = CONFIG_WL_SECTOR_SIZE / 32;
|
||||
}
|
||||
const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (mount_config->use_one_fat ? 1 : 2), 0, (sec_num <= MIN_REQ_SEC ? root_dir_entries : 0), alloc_unit_size};
|
||||
|
||||
const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (mount_config->use_one_fat ? 1 : 2), 0, root_dir_entries, alloc_unit_size};
|
||||
fresult = f_mkfs(drv, &opt, workbuf, workbuf_size);
|
||||
free(workbuf);
|
||||
workbuf = NULL;
|
||||
@@ -121,6 +120,63 @@ static esp_err_t s_f_mount_rw(FATFS *fs, const char *drv, const esp_vfs_fat_moun
|
||||
*out_flags &= ~FORMATTED_DURING_LAST_MOUNT; // reset flag
|
||||
}
|
||||
}
|
||||
|
||||
const char *msg = "Unknown";
|
||||
const char *note = "";
|
||||
bool recoverable = false;
|
||||
|
||||
switch (fresult) {
|
||||
case FR_NO_FILESYSTEM:
|
||||
msg = "No filesystem detected";
|
||||
note = "(This may indicate corrupt FS, or attempt to mount read-only fatfsgen image for write)";
|
||||
recoverable = true;
|
||||
break;
|
||||
case FR_INT_ERR:
|
||||
msg = "Assertion failed";
|
||||
recoverable = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!recoverable || !mount_config->format_if_mount_failed) {
|
||||
ESP_LOGE(TAG, "f_mount failed with error: \"%s\" [%d]. %s", msg, fresult, note);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGW(TAG, "FatFS mount (f_mount) failed with error: \"%s\" [%d]. Retrying after format...", msg, fresult);
|
||||
|
||||
const size_t workbuf_size = 4096;
|
||||
void *workbuf = ff_memalloc(workbuf_size);
|
||||
if (workbuf == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(CONFIG_WL_SECTOR_SIZE, mount_config->allocation_unit_size);
|
||||
ESP_LOGI(TAG, "Formatting FATFS partition, allocation unit size=%d", alloc_unit_size);
|
||||
|
||||
//if root directory entries set as default, allocate whole 1 sector for this purpose (one rootdir entry == 32B)
|
||||
UINT root_dir_entries = mount_config->rootdir_entries;
|
||||
if (root_dir_entries == 0) {
|
||||
root_dir_entries = CONFIG_WL_SECTOR_SIZE / 32;
|
||||
}
|
||||
const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (mount_config->use_one_fat ? 1 : 2), 0, root_dir_entries, alloc_unit_size};
|
||||
ESP_LOGD(TAG, "f_mkfs() params: root_dir_entries: %ul, alloc_unit_size=%ul", root_dir_entries, alloc_unit_size);
|
||||
|
||||
fresult = f_mkfs(drv, &opt, workbuf, workbuf_size);
|
||||
|
||||
free(workbuf);
|
||||
workbuf = NULL;
|
||||
ESP_RETURN_ON_FALSE(fresult == FR_OK, ESP_FAIL, TAG, "f_mkfs failed (%d)", fresult);
|
||||
|
||||
if (out_flags) {
|
||||
*out_flags |= FORMATTED_DURING_LAST_MOUNT; // set flag
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Mounting again");
|
||||
fresult = f_mount(fs, drv, 1);
|
||||
ESP_RETURN_ON_FALSE(fresult == FR_OK, ESP_FAIL, TAG, "f_mount failed after formatting (%d)", fresult);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -132,11 +188,9 @@ esp_err_t esp_vfs_fat_spiflash_mount_rw_wl(const char* base_path,
|
||||
esp_err_t ret = ESP_OK;
|
||||
vfs_fat_spiflash_ctx_t *ctx = NULL;
|
||||
uint32_t ctx_id = FF_VOLUMES;
|
||||
esp_partition_subtype_t subtype = partition_label ? ESP_PARTITION_SUBTYPE_ANY : ESP_PARTITION_SUBTYPE_DATA_FAT;
|
||||
|
||||
esp_partition_subtype_t subtype = partition_label ?
|
||||
ESP_PARTITION_SUBTYPE_ANY : ESP_PARTITION_SUBTYPE_DATA_FAT;
|
||||
const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
|
||||
subtype, partition_label);
|
||||
const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, subtype, partition_label);
|
||||
ESP_RETURN_ON_FALSE(data_partition, ESP_ERR_NOT_FOUND, TAG, "Failed to find FATFS partition (type='data', subtype='fat', partition_label='%s'). Check the partition table.", partition_label);
|
||||
|
||||
ESP_RETURN_ON_ERROR(wl_mount(data_partition, wl_handle), TAG, "failed to mount wear levelling layer. ret = %i", ret);
|
||||
@@ -167,9 +221,8 @@ esp_err_t esp_vfs_fat_spiflash_mount_rw_wl(const char* base_path,
|
||||
|
||||
vfs_fat_x_ctx_flags_t flags = 0;
|
||||
|
||||
size_t sec_num = wl_size(*wl_handle) / wl_sector_size(*wl_handle);
|
||||
// Try to mount partition
|
||||
ret = s_f_mount_rw(fs, drv, mount_config, &flags, sec_num);
|
||||
ret = s_f_mount_rw(fs, drv, mount_config, &flags);
|
||||
if (ret != ESP_OK) {
|
||||
goto fail;
|
||||
}
|
||||
@@ -235,7 +288,6 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha
|
||||
|
||||
wl_handle_t temp_handle = WL_INVALID_HANDLE;
|
||||
uint32_t id = FF_VOLUMES;
|
||||
size_t sec_num = 0;
|
||||
|
||||
bool found = s_get_context_id_by_label(partition_label, &id);
|
||||
if (!found) {
|
||||
@@ -251,7 +303,6 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(esp_vfs_fat_spiflash_mount_rw_wl(base_path, partition_label, mount_cfg, &temp_handle), TAG, "Failed to mount");
|
||||
found = s_get_context_id_by_label(partition_label, &id);
|
||||
sec_num = wl_size(temp_handle) / wl_sector_size(temp_handle);
|
||||
assert(found);
|
||||
if (s_ctx[id]->flags & FORMATTED_DURING_LAST_MOUNT) {
|
||||
ESP_LOGD(TAG, "partition was formatted during mounting, skipping another format");
|
||||
@@ -264,7 +315,6 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha
|
||||
s_ctx[id]->mount_config = *cfg;
|
||||
}
|
||||
temp_handle = s_ctx[id]->wlhandle;
|
||||
sec_num = wl_size(temp_handle) / wl_sector_size(temp_handle);
|
||||
}
|
||||
|
||||
//unmount
|
||||
@@ -281,13 +331,14 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha
|
||||
}
|
||||
size_t alloc_unit_size = esp_vfs_fat_get_allocation_unit_size(CONFIG_WL_SECTOR_SIZE, s_ctx[id]->mount_config.allocation_unit_size);
|
||||
ESP_LOGI(TAG, "Formatting FATFS partition, allocation unit size=%d", alloc_unit_size);
|
||||
UINT root_dir_entries;
|
||||
if (CONFIG_WL_SECTOR_SIZE == 512) {
|
||||
root_dir_entries = 16;
|
||||
} else {
|
||||
root_dir_entries = 128;
|
||||
|
||||
//if root directory entries set as default, allocate whole 1 sector for this purpose (one rootdir entry == 32B)
|
||||
UINT root_dir_entries = s_ctx[id]->mount_config.rootdir_entries;
|
||||
if (root_dir_entries == 0) {
|
||||
root_dir_entries = CONFIG_WL_SECTOR_SIZE / 32;
|
||||
}
|
||||
const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (s_ctx[id]->mount_config.use_one_fat ? 1 : 2), 0, (sec_num <= MIN_REQ_SEC ? root_dir_entries : 0), alloc_unit_size};
|
||||
const MKFS_PARM opt = {(BYTE)(FM_ANY | FM_SFD), (s_ctx[id]->mount_config.use_one_fat ? 1 : 2), 0, root_dir_entries, alloc_unit_size};
|
||||
|
||||
fresult = f_mkfs(drv, &opt, workbuf, workbuf_size);
|
||||
free(workbuf);
|
||||
workbuf = NULL;
|
||||
@@ -295,7 +346,7 @@ esp_err_t esp_vfs_fat_spiflash_format_cfg_rw_wl(const char* base_path, const cha
|
||||
|
||||
mount_back:
|
||||
if (partition_was_mounted) {
|
||||
esp_err_t err = s_f_mount_rw(s_ctx[id]->fs, drv, &s_ctx[id]->mount_config, NULL, sec_num);
|
||||
esp_err_t err = s_f_mount_rw(s_ctx[id]->fs, drv, &s_ctx[id]->mount_config, NULL);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "failed to mount back, go to recycle");
|
||||
goto recycle;
|
||||
|
||||
Reference in New Issue
Block a user