Skip to content

Commit 8606eb4

Browse files
committed
Merge branch 'feat/optimize_vfs_mountpoint_table' into 'master'
feat(storage/vfs): improve mountpoint table memory usage Closes IDF-12560 See merge request espressif/esp-idf!36613
2 parents fec59ec + 6763898 commit 8606eb4

File tree

2 files changed

+66
-28
lines changed

2 files changed

+66
-28
lines changed

components/vfs/private_include/esp_vfs_private.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
/*
2-
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

77
#include "sdkconfig.h"
88
#include "esp_vfs.h"
99
#include "esp_vfs_common.h"
10+
#include <stddef.h>
1011

1112
#ifdef __cplusplus
1213
extern "C" {
@@ -19,12 +20,12 @@ extern "C" {
1920
#endif
2021

2122
typedef struct vfs_entry_ {
22-
int flags; /*!< ESP_VFS_FLAG_CONTEXT_PTR and/or ESP_VFS_FLAG_READONLY_FS or ESP_VFS_FLAG_DEFAULT */
23-
const esp_vfs_fs_ops_t *vfs; // contains pointers to VFS functions
24-
char path_prefix[ESP_VFS_PATH_MAX]; // path prefix mapped to this VFS
25-
size_t path_prefix_len; // micro-optimization to avoid doing extra strlen
26-
void* ctx; // optional pointer which can be passed to VFS
27-
int offset; // index of this structure in s_vfs array
23+
int flags; /*!< ESP_VFS_FLAG_CONTEXT_PTR and/or ESP_VFS_FLAG_READONLY_FS or ESP_VFS_FLAG_DEFAULT */
24+
const esp_vfs_fs_ops_t *vfs; /*!< contains pointers to VFS functions */
25+
void *ctx; /*!< optional pointer which can be passed to VFS */
26+
int offset; /*!< index of this structure in s_vfs array */
27+
size_t path_prefix_len; /*!< micro-optimization to avoid doing extra strlen, contains length of the string, not the size of path_prefix array */
28+
const char path_prefix[]; /*!< path prefix mapped to this VFS */
2829
} vfs_entry_t;
2930

3031
/**
@@ -53,7 +54,7 @@ typedef struct vfs_entry_ {
5354
* ESP_ERR_NO_MEM if too many VFSes are registered.
5455
* ESP_ERR_INVALID_ARG if given an invalid parameter.
5556
*/
56-
esp_err_t esp_vfs_register_common(const char *base_path, size_t len, const esp_vfs_t* vfs, void* ctx, int *vfs_index);
57+
esp_err_t esp_vfs_register_common(const char *base_path, size_t len, const esp_vfs_t *vfs, void *ctx, int *vfs_index);
5758

5859
/**
5960
* Get vfs fd with given path.

components/vfs/vfs.c

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
2+
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -395,20 +395,38 @@ static esp_err_t esp_vfs_make_fs_ops(const esp_vfs_t *vfs, esp_vfs_fs_ops_t **mi
395395
return ESP_ERR_NO_MEM;
396396
}
397397

398-
static esp_err_t esp_vfs_register_fs_common(const char* base_path, size_t len, const esp_vfs_fs_ops_t* vfs, int flags, void* ctx, int *vfs_index)
398+
static bool is_path_prefix_valid(const char *path, size_t length) {
399+
return (length >= 2)
400+
&& (length <= ESP_VFS_PATH_MAX)
401+
&& (path[0] == '/')
402+
&& (path[length - 1] != '/');
403+
}
404+
405+
static esp_err_t esp_vfs_register_fs_common(
406+
const char *base_path,
407+
const esp_vfs_fs_ops_t *vfs,
408+
int flags,
409+
void *ctx,
410+
int *vfs_index)
399411
{
412+
if (s_vfs_count >= VFS_MAX_COUNT) {
413+
return ESP_ERR_NO_MEM;
414+
}
415+
400416
if (vfs == NULL) {
401417
ESP_LOGE(TAG, "VFS is NULL");
402418
return ESP_ERR_INVALID_ARG;
403419
}
404420

405-
if (len != LEN_PATH_PREFIX_IGNORED) {
406-
/* empty prefix is allowed, "/" is not allowed */
407-
if ((len == 1) || (len > ESP_VFS_PATH_MAX)) {
408-
return ESP_ERR_INVALID_ARG;
409-
}
410-
/* prefix has to start with "/" and not end with "/" */
411-
if (len >= 2 && ((base_path[0] != '/') || (base_path[len - 1] == '/'))) {
421+
size_t base_path_len = 0;
422+
const char *_base_path = "";
423+
424+
if (base_path != NULL) {
425+
base_path_len = strlen(base_path);
426+
_base_path = base_path;
427+
428+
if (base_path_len != 0 && !is_path_prefix_valid(base_path, base_path_len)) {
429+
ESP_LOGE(TAG, "Invalid path prefix");
412430
return ESP_ERR_INVALID_ARG;
413431
}
414432
}
@@ -426,23 +444,21 @@ static esp_err_t esp_vfs_register_fs_common(const char* base_path, size_t len, c
426444
s_vfs_count++;
427445
}
428446

429-
vfs_entry_t *entry = (vfs_entry_t*) heap_caps_malloc(sizeof(vfs_entry_t), VFS_MALLOC_FLAGS);
447+
vfs_entry_t *entry = heap_caps_malloc(sizeof(vfs_entry_t) + base_path_len + 1, VFS_MALLOC_FLAGS);
430448
if (entry == NULL) {
431449
return ESP_ERR_NO_MEM;
432450
}
433451

434452
s_vfs[index] = entry;
435-
if (len != LEN_PATH_PREFIX_IGNORED) {
436-
strcpy(entry->path_prefix, base_path); // we have already verified argument length
437-
} else {
438-
bzero(entry->path_prefix, sizeof(entry->path_prefix));
439-
}
440-
entry->path_prefix_len = len;
453+
454+
entry->path_prefix_len = base_path == NULL ? LEN_PATH_PREFIX_IGNORED : base_path_len;
441455
entry->vfs = vfs;
442456
entry->ctx = ctx;
443457
entry->offset = index;
444458
entry->flags = flags;
445459

460+
memcpy((char *)(entry->path_prefix), _base_path, base_path_len + 1);
461+
446462
if (vfs_index) {
447463
*vfs_index = index;
448464
}
@@ -457,16 +473,21 @@ esp_err_t esp_vfs_register_fs(const char* base_path, const esp_vfs_fs_ops_t* vfs
457473
return ESP_ERR_INVALID_ARG;
458474
}
459475

476+
if (base_path == NULL) {
477+
ESP_LOGE(TAG, "base_path cannot be null");
478+
return ESP_ERR_INVALID_ARG;
479+
}
480+
460481
if ((flags & ESP_VFS_FLAG_STATIC)) {
461-
return esp_vfs_register_fs_common(base_path, strlen(base_path), vfs, flags, ctx, NULL);
482+
return esp_vfs_register_fs_common(base_path, vfs, flags, ctx, NULL);
462483
}
463484

464485
esp_vfs_fs_ops_t *_vfs = esp_vfs_duplicate_fs_ops(vfs);
465486
if (_vfs == NULL) {
466487
return ESP_ERR_NO_MEM;
467488
}
468489

469-
esp_err_t ret = esp_vfs_register_fs_common(base_path, strlen(base_path), _vfs, flags, ctx, NULL);
490+
esp_err_t ret = esp_vfs_register_fs_common(base_path, _vfs, flags, ctx, NULL);
470491
if (ret != ESP_OK) {
471492
esp_vfs_free_fs_ops(_vfs);
472493
return ret;
@@ -487,13 +508,29 @@ esp_err_t esp_vfs_register_common(const char* base_path, size_t len, const esp_v
487508
return ESP_ERR_INVALID_ARG;
488509
}
489510

511+
if (len != LEN_PATH_PREFIX_IGNORED) {
512+
if (base_path == NULL) {
513+
ESP_LOGE(TAG, "Path prefix cannot be NULL");
514+
return ESP_ERR_INVALID_ARG;
515+
}
516+
517+
// This is for backwards compatibility
518+
if (strlen(base_path) != len) {
519+
ESP_LOGE(TAG, "Mismatch between real and given path prefix lengths.");
520+
return ESP_ERR_INVALID_ARG;
521+
}
522+
} else {
523+
// New API expects NULL in this case
524+
base_path = NULL;
525+
}
526+
490527
esp_vfs_fs_ops_t *_vfs = NULL;
491528
esp_err_t ret = esp_vfs_make_fs_ops(vfs, &_vfs);
492529
if (ret != ESP_OK) {
493530
return ret;
494531
}
495532

496-
ret = esp_vfs_register_fs_common(base_path, len, _vfs, vfs->flags, ctx, vfs_index);
533+
ret = esp_vfs_register_fs_common(base_path, _vfs, vfs->flags, ctx, vfs_index);
497534
if (ret != ESP_OK) {
498535
esp_vfs_free_fs_ops(_vfs);
499536
return ret;
@@ -551,7 +588,7 @@ esp_err_t esp_vfs_register_fs_with_id(const esp_vfs_fs_ops_t *vfs, int flags, vo
551588
}
552589

553590
*vfs_id = -1;
554-
return esp_vfs_register_fs_common("", LEN_PATH_PREFIX_IGNORED, vfs, flags, ctx, vfs_id);
591+
return esp_vfs_register_fs_common(NULL, vfs, flags, ctx, vfs_id);
555592
}
556593

557594
esp_err_t esp_vfs_register_with_id(const esp_vfs_t *vfs, void *ctx, esp_vfs_id_t *vfs_id)

0 commit comments

Comments
 (0)