@@ -1183,6 +1183,50 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
1183
1183
return err ;
1184
1184
}
1185
1185
1186
+ static int lfs_file_relocate (lfs_t * lfs , lfs_file_t * file ) {
1187
+ relocate :
1188
+ LFS_DEBUG ("Bad block at %d" , file -> block );
1189
+
1190
+ // just relocate what exists into new block
1191
+ lfs_block_t nblock ;
1192
+ int err = lfs_alloc (lfs , & nblock );
1193
+ if (err ) {
1194
+ return err ;
1195
+ }
1196
+
1197
+ // either read from dirty cache or disk
1198
+ for (lfs_off_t i = 0 ; i < file -> off ; i ++ ) {
1199
+ uint8_t data ;
1200
+ if (file -> cache .block == file -> block && i >= file -> cache .off ) {
1201
+ data = file -> cache .buffer [i - file -> cache .off ];
1202
+ } else {
1203
+ // just read from disk
1204
+ err = lfs_bd_read (lfs , file -> block , i , & data , 1 );
1205
+ if (err ) {
1206
+ return err ;
1207
+ }
1208
+ }
1209
+
1210
+ err = lfs_cache_prog (lfs , & lfs -> pcache , & lfs -> rcache ,
1211
+ nblock , i , & data , 1 );
1212
+ if (err ) {
1213
+ if (err == LFS_ERR_CORRUPT ) {
1214
+ goto relocate ;
1215
+ }
1216
+ return err ;
1217
+ }
1218
+ }
1219
+
1220
+ // copy over new state of file
1221
+ memcpy (file -> cache .buffer , lfs -> pcache .buffer , lfs -> cfg -> prog_size );
1222
+ file -> cache .block = lfs -> pcache .block ;
1223
+ file -> cache .off = lfs -> pcache .off ;
1224
+ lfs -> pcache .block = 0xffffffff ;
1225
+
1226
+ file -> block = nblock ;
1227
+ return 0 ;
1228
+ }
1229
+
1186
1230
static int lfs_file_flush (lfs_t * lfs , lfs_file_t * file ) {
1187
1231
if (file -> flags & LFS_F_READING ) {
1188
1232
// just drop read cache
@@ -1225,9 +1269,21 @@ static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
1225
1269
}
1226
1270
1227
1271
// write out what we have
1228
- int err = lfs_cache_flush (lfs , & file -> cache , & lfs -> rcache );
1229
- if (err ) {
1230
- return err ;
1272
+ while (true) {
1273
+ int err = lfs_cache_flush (lfs , & file -> cache , & lfs -> rcache );
1274
+ if (err ) {
1275
+ if (err == LFS_ERR_CORRUPT ) {
1276
+ goto relocate ;
1277
+ }
1278
+ return err ;
1279
+ }
1280
+
1281
+ break ;
1282
+ relocate :
1283
+ err = lfs_file_relocate (lfs , file );
1284
+ if (err ) {
1285
+ return err ;
1286
+ }
1231
1287
}
1232
1288
1233
1289
// actual file updates
@@ -1396,45 +1452,10 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
1396
1452
1397
1453
break ;
1398
1454
relocate :
1399
- LFS_DEBUG ("Bad block at %d" , file -> block );
1400
-
1401
- // just relocate what exists into new block
1402
- lfs_block_t nblock ;
1403
- err = lfs_alloc (lfs , & nblock );
1455
+ err = lfs_file_relocate (lfs , file );
1404
1456
if (err ) {
1405
1457
return err ;
1406
1458
}
1407
-
1408
- // either read from dirty cache or disk
1409
- for (lfs_off_t i = 0 ; i < file -> off ; i ++ ) {
1410
- uint8_t data ;
1411
- if (file -> cache .block == file -> block && i >= file -> cache .off ) {
1412
- data = file -> cache .buffer [i - file -> cache .off ];
1413
- } else {
1414
- // just read from disk
1415
- err = lfs_bd_read (lfs , file -> block , i , & data , 1 );
1416
- if (err ) {
1417
- return err ;
1418
- }
1419
- }
1420
-
1421
- err = lfs_cache_prog (lfs , & lfs -> pcache , & lfs -> rcache ,
1422
- nblock , i , & data , 1 );
1423
- if (err ) {
1424
- if (err == LFS_ERR_CORRUPT ) {
1425
- goto relocate ;
1426
- }
1427
- return err ;
1428
- }
1429
- }
1430
-
1431
- // copy over new state of file
1432
- memcpy (file -> cache .buffer , lfs -> pcache .buffer , lfs -> cfg -> prog_size );
1433
- file -> cache .block = lfs -> pcache .block ;
1434
- file -> cache .off = lfs -> pcache .off ;
1435
- lfs -> pcache .block = 0xffffffff ;
1436
-
1437
- file -> block = nblock ;
1438
1459
}
1439
1460
1440
1461
file -> pos += diff ;
0 commit comments