Skip to content

Commit 68d28b5

Browse files
authored
Merge pull request #966 from BrianPugh/fix-divide-by-zero-full-filesystem
Fix DivideByZero exception when filesystem is completely full.
2 parents 4dd30c1 + 1bc1493 commit 68d28b5

File tree

3 files changed

+62
-25
lines changed

3 files changed

+62
-25
lines changed

lfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
688688
if (lfs->lookahead.ckpoint <= 0) {
689689
LFS_ERROR("No more free space 0x%"PRIx32,
690690
(lfs->lookahead.start + lfs->lookahead.next)
691-
% lfs->cfg->block_count);
691+
% lfs->block_count);
692692
return LFS_ERR_NOSPC;
693693
}
694694

lfs.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ typedef uint32_t lfs_block_t;
5959
#endif
6060

6161
// Maximum size of custom attributes in bytes, may be redefined, but there is
62-
// no real benefit to using a smaller LFS_ATTR_MAX. Limited to <= 1022.
62+
// no real benefit to using a smaller LFS_ATTR_MAX. Limited to <= 1022. Stored
63+
// in superblock and must be respected by other littlefs drivers.
6364
#ifndef LFS_ATTR_MAX
6465
#define LFS_ATTR_MAX 1022
6566
#endif
@@ -203,7 +204,8 @@ struct lfs_config {
203204
// program sizes.
204205
lfs_size_t block_size;
205206

206-
// Number of erasable blocks on the device.
207+
// Number of erasable blocks on the device. Defaults to block_count stored
208+
// on disk when zero.
207209
lfs_size_t block_count;
208210

209211
// Number of erase cycles before littlefs evicts metadata logs and moves
@@ -252,18 +254,18 @@ struct lfs_config {
252254

253255
// Optional upper limit on length of file names in bytes. No downside for
254256
// larger names except the size of the info struct which is controlled by
255-
// the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX when zero. Stored in
256-
// superblock and must be respected by other littlefs drivers.
257+
// the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX or name_max stored on
258+
// disk when zero.
257259
lfs_size_t name_max;
258260

259261
// Optional upper limit on files in bytes. No downside for larger files
260-
// but must be <= LFS_FILE_MAX. Defaults to LFS_FILE_MAX when zero. Stored
261-
// in superblock and must be respected by other littlefs drivers.
262+
// but must be <= LFS_FILE_MAX. Defaults to LFS_FILE_MAX or file_max stored
263+
// on disk when zero.
262264
lfs_size_t file_max;
263265

264266
// Optional upper limit on custom attributes in bytes. No downside for
265267
// larger attributes size but must be <= LFS_ATTR_MAX. Defaults to
266-
// LFS_ATTR_MAX when zero.
268+
// LFS_ATTR_MAX or attr_max stored on disk when zero.
267269
lfs_size_t attr_max;
268270

269271
// Optional upper limit on total space given to metadata pairs in bytes. On

tests/test_alloc.toml

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,22 @@ defines.FILES = 3
88
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)'
99
defines.GC = [false, true]
1010
defines.COMPACT_THRESH = ['-1', '0', 'BLOCK_SIZE/2']
11+
defines.INFER_BC = [false, true]
1112
code = '''
1213
const char *names[] = {"bacon", "eggs", "pancakes"};
1314
lfs_file_t files[FILES];
1415
1516
lfs_t lfs;
1617
lfs_format(&lfs, cfg) => 0;
17-
lfs_mount(&lfs, cfg) => 0;
18+
struct lfs_config cfg_ = *cfg;
19+
if (INFER_BC) {
20+
cfg_.block_count = 0;
21+
}
22+
lfs_mount(&lfs, &cfg_) => 0;
1823
lfs_mkdir(&lfs, "breakfast") => 0;
1924
lfs_unmount(&lfs) => 0;
2025
21-
lfs_mount(&lfs, cfg) => 0;
26+
lfs_mount(&lfs, &cfg_) => 0;
2227
for (int n = 0; n < FILES; n++) {
2328
char path[1024];
2429
sprintf(path, "breakfast/%s", names[n]);
@@ -39,7 +44,7 @@ code = '''
3944
}
4045
lfs_unmount(&lfs) => 0;
4146
42-
lfs_mount(&lfs, cfg) => 0;
47+
lfs_mount(&lfs, &cfg_) => 0;
4348
for (int n = 0; n < FILES; n++) {
4449
char path[1024];
4550
sprintf(path, "breakfast/%s", names[n]);
@@ -62,17 +67,22 @@ defines.FILES = 3
6267
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)'
6368
defines.GC = [false, true]
6469
defines.COMPACT_THRESH = ['-1', '0', 'BLOCK_SIZE/2']
70+
defines.INFER_BC = [false, true]
6571
code = '''
6672
const char *names[] = {"bacon", "eggs", "pancakes"};
6773
6874
lfs_t lfs;
6975
lfs_format(&lfs, cfg) => 0;
70-
lfs_mount(&lfs, cfg) => 0;
76+
struct lfs_config cfg_ = *cfg;
77+
if (INFER_BC) {
78+
cfg_.block_count = 0;
79+
}
80+
lfs_mount(&lfs, &cfg_) => 0;
7181
lfs_mkdir(&lfs, "breakfast") => 0;
7282
lfs_unmount(&lfs) => 0;
7383
7484
for (int n = 0; n < FILES; n++) {
75-
lfs_mount(&lfs, cfg) => 0;
85+
lfs_mount(&lfs, &cfg_) => 0;
7686
char path[1024];
7787
sprintf(path, "breakfast/%s", names[n]);
7888
lfs_file_t file;
@@ -91,7 +101,7 @@ code = '''
91101
lfs_unmount(&lfs) => 0;
92102
}
93103
94-
lfs_mount(&lfs, cfg) => 0;
104+
lfs_mount(&lfs, &cfg_) => 0;
95105
for (int n = 0; n < FILES; n++) {
96106
char path[1024];
97107
sprintf(path, "breakfast/%s", names[n]);
@@ -113,19 +123,24 @@ code = '''
113123
defines.FILES = 3
114124
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)'
115125
defines.CYCLES = [1, 10]
126+
defines.INFER_BC = [false, true]
116127
code = '''
117128
const char *names[] = {"bacon", "eggs", "pancakes"};
118129
lfs_file_t files[FILES];
119130
120131
lfs_t lfs;
121132
lfs_format(&lfs, cfg) => 0;
133+
struct lfs_config cfg_ = *cfg;
134+
if (INFER_BC) {
135+
cfg_.block_count = 0;
136+
}
122137
123138
for (int c = 0; c < CYCLES; c++) {
124-
lfs_mount(&lfs, cfg) => 0;
139+
lfs_mount(&lfs, &cfg_) => 0;
125140
lfs_mkdir(&lfs, "breakfast") => 0;
126141
lfs_unmount(&lfs) => 0;
127142
128-
lfs_mount(&lfs, cfg) => 0;
143+
lfs_mount(&lfs, &cfg_) => 0;
129144
for (int n = 0; n < FILES; n++) {
130145
char path[1024];
131146
sprintf(path, "breakfast/%s", names[n]);
@@ -143,7 +158,7 @@ code = '''
143158
}
144159
lfs_unmount(&lfs) => 0;
145160
146-
lfs_mount(&lfs, cfg) => 0;
161+
lfs_mount(&lfs, &cfg_) => 0;
147162
for (int n = 0; n < FILES; n++) {
148163
char path[1024];
149164
sprintf(path, "breakfast/%s", names[n]);
@@ -159,7 +174,7 @@ code = '''
159174
}
160175
lfs_unmount(&lfs) => 0;
161176
162-
lfs_mount(&lfs, cfg) => 0;
177+
lfs_mount(&lfs, &cfg_) => 0;
163178
for (int n = 0; n < FILES; n++) {
164179
char path[1024];
165180
sprintf(path, "breakfast/%s", names[n]);
@@ -175,19 +190,24 @@ code = '''
175190
defines.FILES = 3
176191
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)'
177192
defines.CYCLES = [1, 10]
193+
defines.INFER_BC = [false, true]
178194
code = '''
179195
const char *names[] = {"bacon", "eggs", "pancakes"};
180196
181197
lfs_t lfs;
182198
lfs_format(&lfs, cfg) => 0;
199+
struct lfs_config cfg_ = *cfg;
200+
if (INFER_BC) {
201+
cfg_.block_count = 0;
202+
}
183203
184204
for (int c = 0; c < CYCLES; c++) {
185-
lfs_mount(&lfs, cfg) => 0;
205+
lfs_mount(&lfs, &cfg_) => 0;
186206
lfs_mkdir(&lfs, "breakfast") => 0;
187207
lfs_unmount(&lfs) => 0;
188208
189209
for (int n = 0; n < FILES; n++) {
190-
lfs_mount(&lfs, cfg) => 0;
210+
lfs_mount(&lfs, &cfg_) => 0;
191211
char path[1024];
192212
sprintf(path, "breakfast/%s", names[n]);
193213
lfs_file_t file;
@@ -232,10 +252,15 @@ code = '''
232252

233253
# exhaustion test
234254
[cases.test_alloc_exhaustion]
255+
defines.INFER_BC = [false, true]
235256
code = '''
236257
lfs_t lfs;
237258
lfs_format(&lfs, cfg) => 0;
238-
lfs_mount(&lfs, cfg) => 0;
259+
struct lfs_config cfg_ = *cfg;
260+
if (INFER_BC) {
261+
cfg_.block_count = 0;
262+
}
263+
lfs_mount(&lfs, &cfg_) => 0;
239264
lfs_file_t file;
240265
lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT);
241266
size_t size = strlen("exhaustion");
@@ -263,7 +288,7 @@ code = '''
263288
lfs_file_close(&lfs, &file) => 0;
264289
lfs_unmount(&lfs) => 0;
265290
266-
lfs_mount(&lfs, cfg) => 0;
291+
lfs_mount(&lfs, &cfg_) => 0;
267292
lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY);
268293
size = strlen("exhaustion");
269294
lfs_file_size(&lfs, &file) => size;
@@ -276,10 +301,15 @@ code = '''
276301
# exhaustion wraparound test
277302
[cases.test_alloc_exhaustion_wraparound]
278303
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-4)) / 3)'
304+
defines.INFER_BC = [false, true]
279305
code = '''
280306
lfs_t lfs;
281307
lfs_format(&lfs, cfg) => 0;
282-
lfs_mount(&lfs, cfg) => 0;
308+
struct lfs_config cfg_ = *cfg;
309+
if (INFER_BC) {
310+
cfg_.block_count = 0;
311+
}
312+
lfs_mount(&lfs, &cfg_) => 0;
283313
284314
lfs_file_t file;
285315
lfs_file_open(&lfs, &file, "padding", LFS_O_WRONLY | LFS_O_CREAT);
@@ -317,7 +347,7 @@ code = '''
317347
lfs_file_close(&lfs, &file) => 0;
318348
lfs_unmount(&lfs) => 0;
319349
320-
lfs_mount(&lfs, cfg) => 0;
350+
lfs_mount(&lfs, &cfg_) => 0;
321351
lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY);
322352
size = strlen("exhaustion");
323353
lfs_file_size(&lfs, &file) => size;
@@ -330,10 +360,15 @@ code = '''
330360

331361
# dir exhaustion test
332362
[cases.test_alloc_dir_exhaustion]
363+
defines.INFER_BC = [false, true]
333364
code = '''
334365
lfs_t lfs;
335366
lfs_format(&lfs, cfg) => 0;
336-
lfs_mount(&lfs, cfg) => 0;
367+
struct lfs_config cfg_ = *cfg;
368+
if (INFER_BC) {
369+
cfg_.block_count = 0;
370+
}
371+
lfs_mount(&lfs, &cfg_) => 0;
337372
338373
// find out max file size
339374
lfs_mkdir(&lfs, "exhaustiondir") => 0;

0 commit comments

Comments
 (0)