@@ -189,103 +189,60 @@ static int lfs_bd_cmp(lfs_t *lfs, lfs_block_t block,
189
189
static int lfs_alloc_lookahead (void * p , lfs_block_t block ) {
190
190
lfs_t * lfs = p ;
191
191
192
- lfs_block_t off = block - lfs -> free .begin ;
193
- if (off < LFS_CFG_LOOKAHEAD ) {
194
- lfs -> lookahead [off / 32 ] |= 1U << (off % 32 );
192
+ lfs_block_t off = ( block - lfs -> free .start ) % lfs -> cfg -> block_count ;
193
+ if (off < lfs -> cfg -> lookahead ) {
194
+ lfs -> free . lookahead [off / 32 ] |= 1U << (off % 32 );
195
195
}
196
196
197
197
return 0 ;
198
198
}
199
199
200
- static int lfs_alloc_stride (void * p , lfs_block_t block ) {
201
- lfs_t * lfs = p ;
202
-
203
- lfs_block_t noff = block - lfs -> free .begin ;
204
- lfs_block_t off = lfs -> free .end - lfs -> free .begin ;
205
- if (noff < off ) {
206
- lfs -> free .end = noff + lfs -> free .begin ;
207
- }
208
-
209
- return 0 ;
210
- }
211
-
212
- static int lfs_alloc_scan (lfs_t * lfs ) {
213
- lfs_block_t start = lfs -> free .begin ;
200
+ static int lfs_alloc_scan (lfs_t * lfs , lfs_block_t * block ) {
201
+ lfs_block_t end = lfs -> free .start + lfs -> cfg -> block_count ;
214
202
215
203
while (true) {
216
- // mask out blocks in lookahead region
217
- memset (lfs -> lookahead , 0 , sizeof (lfs -> lookahead ));
218
- int err = lfs_traverse (lfs , lfs_alloc_lookahead , lfs );
219
- if (err ) {
220
- return err ;
221
- }
222
-
223
- // check if we've found a free block
224
- for (uint32_t off = 0 ; off < LFS_CFG_LOOKAHEAD ; off ++ ) {
225
- if (lfs -> lookahead [off / 32 ] & (1U << (off % 32 ))) {
226
- continue ;
204
+ while (lfs -> free .off < lfs -> cfg -> lookahead ) {
205
+ lfs_block_t off = lfs -> free .off ;
206
+ lfs -> free .off += 1 ;
207
+
208
+ if (!(lfs -> free .lookahead [off / 32 ] & (1U << (off % 32 )))) {
209
+ // found a free block
210
+ * block = (lfs -> free .start + off ) % lfs -> cfg -> block_count ;
211
+ return 0 ;
227
212
}
228
-
229
- // found free block, now find stride of free blocks
230
- // since this is relatively cheap (stress on relatively)
231
- lfs -> free .begin += off ;
232
- lfs -> free .end = lfs -> cfg -> block_count ; // before superblock
233
-
234
- // find maximum stride in tree
235
- return lfs_traverse (lfs , lfs_alloc_stride , lfs );
236
213
}
237
214
238
- // continue to next lookahead unless we've searched the whole device
239
- if (start - 1 - lfs -> free .begin < LFS_CFG_LOOKAHEAD ) {
240
- return 0 ;
215
+ // could not find block
216
+ lfs -> free .start += lfs -> cfg -> lookahead ;
217
+ lfs -> free .off = 0 ;
218
+ if (lfs_scmp (lfs -> free .start , end ) > 0 ) {
219
+ return LFS_ERROR_NO_SPACE ;
241
220
}
242
221
243
- // continue to next lookahead region
244
- lfs -> free .begin += LFS_CFG_LOOKAHEAD ;
245
- }
246
- }
247
-
248
- static int lfs_alloc (lfs_t * lfs , lfs_block_t * block ) {
249
- // If we don't remember any free blocks we will need to start searching
250
- if (lfs -> free .begin == lfs -> free .end ) {
251
- int err = lfs_alloc_scan (lfs );
222
+ // find mask of free blocks from tree
223
+ memset (lfs -> free .lookahead , 0 , lfs -> cfg -> lookahead /8 );
224
+ int err = lfs_traverse (lfs , lfs_alloc_lookahead , lfs );
252
225
if (err ) {
253
226
return err ;
254
227
}
255
-
256
- if (lfs -> free .begin == lfs -> free .end ) {
257
- // Still can't allocate a block? check for orphans
258
- int err = lfs_deorphan (lfs );
259
- if (err ) {
260
- return err ;
261
- }
262
-
263
- err = lfs_alloc_scan (lfs );
264
- if (err ) {
265
- return err ;
266
- }
267
-
268
- if (lfs -> free .begin == lfs -> free .end ) {
269
- // Ok, it's true, we're out of space
270
- return LFS_ERROR_NO_SPACE ;
271
- }
272
- }
273
228
}
274
-
275
- // Take first available block
276
- * block = lfs -> free .begin ;
277
- lfs -> free .begin += 1 ;
278
- return 0 ;
279
229
}
280
230
281
- static int lfs_alloc_erased (lfs_t * lfs , lfs_block_t * block ) {
282
- // TODO rm me?
283
- int err = lfs_alloc (lfs , block );
231
+ static int lfs_alloc (lfs_t * lfs , lfs_block_t * block ) {
232
+ // try to scan for free block
233
+ int err = lfs_alloc_scan (lfs , block );
234
+ if (err != LFS_ERROR_NO_SPACE ) {
235
+ return err ;
236
+ }
237
+
238
+ // still can't allocate a block? check for orphans
239
+ err = lfs_deorphan (lfs );
284
240
if (err ) {
285
241
return err ;
286
242
}
287
243
288
- return lfs_bd_erase (lfs , * block );
244
+ // scan again or die trying
245
+ return lfs_alloc_scan (lfs , block );
289
246
}
290
247
291
248
@@ -343,7 +300,12 @@ static int lfs_index_append(lfs_t *lfs, lfs_block_t *headp,
343
300
344
301
while (ioff % lfs -> words == 0 ) {
345
302
lfs_block_t nhead ;
346
- int err = lfs_alloc_erased (lfs , & nhead );
303
+ int err = lfs_alloc (lfs , & nhead );
304
+ if (err ) {
305
+ return err ;
306
+ }
307
+
308
+ err = lfs_bd_erase (lfs , nhead );
347
309
if (err ) {
348
310
return err ;
349
311
}
@@ -480,7 +442,7 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir) {
480
442
static int lfs_dir_fetch (lfs_t * lfs ,
481
443
lfs_dir_t * dir , const lfs_block_t pair [2 ]) {
482
444
// copy out pair, otherwise may be aliasing dir
483
- const lfs_block_t tpair [2 ] = {pair [0 ], pair [1 ]};
445
+ const lfs_block_t tpair [2 ] = {pair [0 ], pair [1 ]};
484
446
bool valid = false;
485
447
486
448
// check both blocks for the most recent revision
@@ -1048,15 +1010,25 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
1048
1010
lfs_off_t woff = file -> size % lfs -> cfg -> block_size ;
1049
1011
1050
1012
if (file -> size == 0 ) {
1051
- int err = lfs_alloc_erased (lfs , & file -> wblock );
1013
+ int err = lfs_alloc (lfs , & file -> wblock );
1014
+ if (err ) {
1015
+ return err ;
1016
+ }
1017
+
1018
+ err = lfs_bd_erase (lfs , file -> wblock );
1052
1019
if (err ) {
1053
1020
return err ;
1054
1021
}
1055
1022
1056
1023
file -> head = file -> wblock ;
1057
1024
file -> windex = 0 ;
1058
1025
} else if (woff == 0 ) {
1059
- int err = lfs_alloc_erased (lfs , & file -> wblock );
1026
+ int err = lfs_alloc (lfs , & file -> wblock );
1027
+ if (err ) {
1028
+ return err ;
1029
+ }
1030
+
1031
+ err = lfs_bd_erase (lfs , file -> wblock );
1060
1032
if (err ) {
1061
1033
return err ;
1062
1034
}
@@ -1124,9 +1096,9 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
1124
1096
static int lfs_init (lfs_t * lfs , const struct lfs_config * cfg ) {
1125
1097
lfs -> cfg = cfg ;
1126
1098
lfs -> words = lfs -> cfg -> block_size / sizeof (uint32_t );
1127
- lfs -> rcache .off = -1 ;
1128
- lfs -> pcache .off = -1 ;
1129
1099
1100
+ // setup read cache
1101
+ lfs -> rcache .off = -1 ;
1130
1102
if (lfs -> cfg -> read_buffer ) {
1131
1103
lfs -> rcache .buffer = lfs -> cfg -> read_buffer ;
1132
1104
} else {
@@ -1136,6 +1108,8 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
1136
1108
}
1137
1109
}
1138
1110
1111
+ // setup program cache
1112
+ lfs -> pcache .off = -1 ;
1139
1113
if (lfs -> cfg -> prog_buffer ) {
1140
1114
lfs -> pcache .buffer = lfs -> cfg -> prog_buffer ;
1141
1115
} else {
@@ -1145,6 +1119,16 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
1145
1119
}
1146
1120
}
1147
1121
1122
+ // setup lookahead
1123
+ if (lfs -> cfg -> lookahead_buffer ) {
1124
+ lfs -> free .lookahead = lfs -> cfg -> lookahead_buffer ;
1125
+ } else {
1126
+ lfs -> free .lookahead = malloc (lfs -> cfg -> lookahead /8 );
1127
+ if (!lfs -> free .lookahead ) {
1128
+ return LFS_ERROR_NO_MEM ;
1129
+ }
1130
+ }
1131
+
1148
1132
return 0 ;
1149
1133
}
1150
1134
@@ -1167,9 +1151,10 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
1167
1151
return err ;
1168
1152
}
1169
1153
1170
- // Create free list
1171
- lfs -> free .begin = 0 ;
1172
- lfs -> free .end = lfs -> cfg -> block_count - 1 ;
1154
+ // Create free lookahead
1155
+ memset (lfs -> free .lookahead , 0 , lfs -> cfg -> lookahead /8 );
1156
+ lfs -> free .start = 0 ;
1157
+ lfs -> free .off = 0 ;
1173
1158
1174
1159
// Create superblock dir
1175
1160
lfs_dir_t superdir ;
@@ -1235,6 +1220,11 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
1235
1220
return err ;
1236
1221
}
1237
1222
1223
+ // setup free lookahead
1224
+ lfs -> free .start = - lfs -> cfg -> lookahead ;
1225
+ lfs -> free .off = lfs -> cfg -> lookahead ;
1226
+
1227
+ // load superblock
1238
1228
lfs_dir_t dir ;
1239
1229
lfs_superblock_t superblock ;
1240
1230
err = lfs_dir_fetch (lfs , & dir , (const lfs_block_t [2 ]){0 , 1 });
0 commit comments