Skip to content

Commit 50892ef

Browse files
committed
Merge branch 'bugfix/spiffs_obj_name_len_check' into 'master'
SPIFFS: fix issues with formatting and page size limit See merge request idf/esp-idf!1866
2 parents f51880f + 1103e1b commit 50892ef

File tree

4 files changed

+111
-48
lines changed

4 files changed

+111
-48
lines changed

components/spiffs/Kconfig

Lines changed: 39 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,78 +5,84 @@ config SPIFFS_MAX_PARTITIONS
55
default 3
66
range 1 10
77
help
8-
Define maximum number of partitions
9-
that can be mounted.
8+
Define maximum number of partitions that can be mounted.
109

1110
menu "SPIFFS Cache Configuration"
1211
config SPIFFS_CACHE
1312
bool "Enable SPIFFS Cache"
1413
default "y"
1514
help
16-
Enables/disable memory read
17-
caching of nucleus file system
15+
Enables/disable memory read caching of nucleus file system
1816
operations.
1917

2018
config SPIFFS_CACHE_WR
2119
bool "Enable SPIFFS Write Caching"
2220
default "y"
2321
depends on SPIFFS_CACHE
2422
help
25-
Enables memory write caching for
26-
file descriptors in hydrogen.
23+
Enables memory write caching for file descriptors in hydrogen.
2724

2825
config SPIFFS_CACHE_STATS
2926
bool "Enable SPIFFS Cache Statistics"
3027
default "n"
3128
depends on SPIFFS_CACHE
3229
help
33-
Enable/disable statistics on caching.
34-
Debug/test purpose only.
30+
Enable/disable statistics on caching. Debug/test purpose only.
3531

3632
endmenu
3733

3834
config SPIFFS_PAGE_CHECK
3935
bool "Enable SPIFFS Page Check"
4036
default "y"
4137
help
42-
Always check header of each
43-
accessed page to ensure consistent state.
44-
If enabled it will increase number
45-
of reads, will increase flash.
38+
Always check header of each accessed page to ensure consistent state.
39+
If enabled it will increase number of reads from flash, especially
40+
if cache is disabled.
4641

4742
config SPIFFS_GC_MAX_RUNS
4843
int "Set Maximum GC Runs"
4944
default 10
5045
range 1 255
5146
help
52-
Define maximum number of gc runs to
53-
perform to reach desired free pages.
47+
Define maximum number of GC runs to perform to reach desired free pages.
5448

5549
config SPIFFS_GC_STATS
5650
bool "Enable SPIFFS GC Statistics"
5751
default "n"
5852
help
59-
Enable/disable statistics on gc.
60-
Debug/test purpose only.
53+
Enable/disable statistics on gc. Debug/test purpose only.
54+
55+
config SPIFFS_PAGE_SIZE
56+
int "SPIFFS logical page size"
57+
default 256
58+
range 256 1024
59+
help
60+
Logical page size of SPIFFS partition, in bytes. Must be multiple
61+
of flash page size (which is usually 256 bytes).
62+
Larger page sizes reduce overhead when storing large files, and
63+
improve filesystem performance when reading large files.
64+
Smaller page sizes reduce overhead when storing small (< page size)
65+
files.
6166

6267
config SPIFFS_OBJ_NAME_LEN
6368
int "Set SPIFFS Maximum Name Length"
6469
default 32
6570
range 1 256
6671
help
67-
Object name maximum length. Note that this length
68-
include the zero-termination character,
69-
meaning maximum string of characters can at most be
70-
SPIFFS_OBJ_NAME_LEN - 1.
72+
Object name maximum length. Note that this length include the
73+
zero-termination character, meaning maximum string of characters
74+
can at most be SPIFFS_OBJ_NAME_LEN - 1.
75+
76+
SPIFFS_OBJ_NAME_LEN + SPIFFS_META_LENGTH should not exceed
77+
SPIFFS_PAGE_SIZE - 64.
7178

7279
config SPIFFS_USE_MAGIC
7380
bool "Enable SPIFFS Filesystem Magic"
7481
default "y"
7582
help
7683
Enable this to have an identifiable spiffs filesystem.
77-
This will look for a magic in all sectors
78-
to determine if this is a valid spiffs system
79-
or not on mount point.
84+
This will look for a magic in all sectors to determine if this
85+
is a valid spiffs system or not at mount time.
8086

8187
config SPIFFS_USE_MAGIC_LENGTH
8288
bool "Enable SPIFFS Filesystem Length Magic"
@@ -96,6 +102,9 @@ config SPIFFS_META_LENGTH
96102
These bytes can be used in an application-specific manner.
97103
Set this to at least 4 bytes to enable support for saving file
98104
modification time.
105+
106+
SPIFFS_OBJ_NAME_LEN + SPIFFS_META_LENGTH should not exceed
107+
SPIFFS_PAGE_SIZE - 64.
99108

100109
config SPIFFS_USE_MTIME
101110
bool "Save file modification time"
@@ -113,45 +122,39 @@ config SPIFFS_DBG
113122
bool "Enable general SPIFFS debug"
114123
default "n"
115124
help
116-
Enabling this option will print
117-
general debug mesages to the console
125+
Enabling this option will print general debug mesages to the console.
118126

119127
config SPIFFS_API_DBG
120128
bool "Enable SPIFFS API debug"
121129
default "n"
122130
help
123-
Enabling this option will print
124-
API debug mesages to the console
131+
Enabling this option will print API debug mesages to the console.
125132

126133
config SPIFFS_GC_DBG
127134
bool "Enable SPIFFS Garbage Cleaner debug"
128135
default "n"
129136
help
130-
Enabling this option will print
131-
GC debug mesages to the console
137+
Enabling this option will print GC debug mesages to the console.
132138

133139
config SPIFFS_CACHE_DBG
134140
bool "Enable SPIFFS Cache debug"
135141
default "n"
136142
depends on SPIFFS_CACHE
137143
help
138-
Enabling this option will print
139-
Cache debug mesages to the console
144+
Enabling this option will print cache debug mesages to the console.
140145

141146
config SPIFFS_CHECK_DBG
142147
bool "Enable SPIFFS Filesystem Check debug"
143148
default "n"
144149
help
145-
Enabling this option will print
146-
Filesystem Check debug mesages
147-
to the console
150+
Enabling this option will print Filesystem Check debug mesages
151+
to the console.
148152

149153
config SPIFFS_TEST_VISUALISATION
150154
bool "Enable SPIFFS Filesystem Visualization"
151155
default "n"
152156
help
153-
Enable this option to enable SPIFFS_vis function
154-
in the api.
157+
Enable this option to enable SPIFFS_vis function in the API.
155158

156159
endmenu
157160

components/spiffs/esp_spiffs.c

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,14 @@ static esp_err_t esp_spiffs_init(const esp_vfs_spiffs_conf_t* conf)
222222
return ESP_ERR_INVALID_STATE;
223223
}
224224

225+
uint32_t flash_page_size = g_rom_flashchip.page_size;
226+
uint32_t log_page_size = CONFIG_SPIFFS_PAGE_SIZE;
227+
if (log_page_size % flash_page_size != 0) {
228+
ESP_LOGE(TAG, "SPIFFS_PAGE_SIZE is not multiple of flash chip page size (%d)",
229+
flash_page_size);
230+
return ESP_ERR_INVALID_ARG;
231+
}
232+
225233
esp_partition_subtype_t subtype = conf->partition_label ?
226234
ESP_PARTITION_SUBTYPE_ANY : ESP_PARTITION_SUBTYPE_DATA_SPIFFS;
227235
const esp_partition_t* partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
@@ -247,7 +255,7 @@ static esp_err_t esp_spiffs_init(const esp_vfs_spiffs_conf_t* conf)
247255
efs->cfg.hal_read_f = spiffs_api_read;
248256
efs->cfg.hal_write_f = spiffs_api_write;
249257
efs->cfg.log_block_size = g_rom_flashchip.sector_size;
250-
efs->cfg.log_page_size = g_rom_flashchip.page_size;
258+
efs->cfg.log_page_size = log_page_size;
251259
efs->cfg.phys_addr = 0;
252260
efs->cfg.phys_erase_block = g_rom_flashchip.sector_size;
253261
efs->cfg.phys_size = partition->size;
@@ -349,8 +357,12 @@ esp_err_t esp_spiffs_info(const char* partition_label, size_t *total_bytes, size
349357

350358
esp_err_t esp_spiffs_format(const char* partition_label)
351359
{
352-
bool mount_on_success = false;
360+
bool partition_was_mounted = false;
353361
int index;
362+
/* If the partition is not mounted, need to create SPIFFS structures
363+
* and mount the partition, unmount, format, delete SPIFFS structures.
364+
* See SPIFFS wiki for the reason why.
365+
*/
354366
esp_err_t err = esp_spiffs_by_label(partition_label, &index);
355367
if (err != ESP_OK) {
356368
esp_vfs_spiffs_conf_t conf = {
@@ -363,23 +375,28 @@ esp_err_t esp_spiffs_format(const char* partition_label)
363375
return err;
364376
}
365377
err = esp_spiffs_by_label(partition_label, &index);
366-
if (err != ESP_OK) {
367-
return err;
368-
}
369-
esp_spiffs_free(&_efs[index]);
370-
return ESP_OK;
378+
assert(err == ESP_OK && "failed to get index of the partition just mounted");
371379
} else if (SPIFFS_mounted(_efs[index]->fs)) {
372-
SPIFFS_unmount(_efs[index]->fs);
373-
mount_on_success = true;
380+
partition_was_mounted = true;
374381
}
382+
383+
SPIFFS_unmount(_efs[index]->fs);
384+
375385
s32_t res = SPIFFS_format(_efs[index]->fs);
376386
if (res != SPIFFS_OK) {
377387
ESP_LOGE(TAG, "format failed, %i", SPIFFS_errno(_efs[index]->fs));
378388
SPIFFS_clearerr(_efs[index]->fs);
389+
/* If the partition was previously mounted, but format failed, don't
390+
* try to mount the partition back (it will probably fail). On the
391+
* other hand, if it was not mounted, need to clean up.
392+
*/
393+
if (!partition_was_mounted) {
394+
esp_spiffs_free(&_efs[index]);
395+
}
379396
return ESP_FAIL;
380397
}
381398

382-
if (mount_on_success) {
399+
if (partition_was_mounted) {
383400
res = SPIFFS_mount(_efs[index]->fs, &_efs[index]->cfg, _efs[index]->work,
384401
_efs[index]->fds, _efs[index]->fds_sz, _efs[index]->cache,
385402
_efs[index]->cache_sz, spiffs_api_check);
@@ -388,6 +405,8 @@ esp_err_t esp_spiffs_format(const char* partition_label)
388405
SPIFFS_clearerr(_efs[index]->fs);
389406
return ESP_FAIL;
390407
}
408+
} else {
409+
esp_spiffs_free(&_efs[index]);
391410
}
392411
return ESP_OK;
393412
}

components/spiffs/include/spiffs_config.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,12 +153,15 @@ extern void spiffs_api_unlock(struct spiffs_t *fs);
153153
// changes the on-disk format, so the change is not backward-compatible.
154154
//
155155
// Do note: the meta length must never exceed
156-
// logical_page_size - (SPIFFS_OBJ_NAME_LEN + 64)
156+
// logical_page_size - (SPIFFS_OBJ_NAME_LEN + SPIFFS_PAGE_EXTRA_SIZE)
157157
//
158158
// This is derived from following:
159159
// logical_page_size - (SPIFFS_OBJ_NAME_LEN + sizeof(spiffs_page_header) +
160160
// spiffs_object_ix_header fields + at least some LUT entries)
161161
#define SPIFFS_OBJ_META_LEN (CONFIG_SPIFFS_META_LENGTH)
162+
#define SPIFFS_PAGE_EXTRA_SIZE (64)
163+
_Static_assert(SPIFFS_OBJ_META_LEN + SPIFFS_OBJ_NAME_LEN + SPIFFS_PAGE_EXTRA_SIZE
164+
<= CONFIG_SPIFFS_PAGE_SIZE, "SPIFFS_OBJ_META_LEN or SPIFFS_OBJ_NAME_LEN too long");
162165

163166
// Size of buffer allocated on stack used when copying data.
164167
// Lower value generates more read/writes. No meaning having it bigger

components/spiffs/test/test_spiffs.c

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ static void test_teardown()
407407
TEST_ESP_OK(esp_vfs_spiffs_unregister(spiffs_test_partition_label));
408408
}
409409

410-
TEST_CASE("can format partition", "[spiffs]")
410+
TEST_CASE("can initialize SPIFFS in erased partition", "[spiffs]")
411411
{
412412
const esp_partition_t* part = get_test_data_partition();
413413
TEST_ASSERT_NOT_NULL(part);
@@ -420,6 +420,44 @@ TEST_CASE("can format partition", "[spiffs]")
420420
test_teardown();
421421
}
422422

423+
TEST_CASE("can format mounted partition", "[spiffs]")
424+
{
425+
// Mount SPIFFS, create file, format, check that the file does not exist.
426+
const esp_partition_t* part = get_test_data_partition();
427+
TEST_ASSERT_NOT_NULL(part);
428+
test_setup();
429+
const char* filename = "/spiffs/hello.txt";
430+
test_spiffs_create_file_with_text(filename, spiffs_test_hello_str);
431+
esp_spiffs_format(part->label);
432+
FILE* f = fopen(filename, "r");
433+
TEST_ASSERT_NULL(f);
434+
test_teardown();
435+
}
436+
437+
TEST_CASE("can format unmounted partition", "[spiffs]")
438+
{
439+
// Mount SPIFFS, create file, unmount. Format. Mount again, check that
440+
// the file does not exist.
441+
const esp_partition_t* part = get_test_data_partition();
442+
TEST_ASSERT_NOT_NULL(part);
443+
test_setup();
444+
const char* filename = "/spiffs/hello.txt";
445+
test_spiffs_create_file_with_text(filename, spiffs_test_hello_str);
446+
test_teardown();
447+
esp_spiffs_format(part->label);
448+
// Don't use test_setup here, need to mount without formatting
449+
esp_vfs_spiffs_conf_t conf = {
450+
.base_path = "/spiffs",
451+
.partition_label = spiffs_test_partition_label,
452+
.max_files = 5,
453+
.format_if_mount_failed = false
454+
};
455+
TEST_ESP_OK(esp_vfs_spiffs_register(&conf));
456+
FILE* f = fopen(filename, "r");
457+
TEST_ASSERT_NULL(f);
458+
test_teardown();
459+
}
460+
423461
TEST_CASE("can create and write file", "[spiffs]")
424462
{
425463
test_setup();

0 commit comments

Comments
 (0)