@@ -1183,6 +1183,50 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
11831183 return err ;
11841184}
11851185
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+
11861230static int lfs_file_flush (lfs_t * lfs , lfs_file_t * file ) {
11871231 if (file -> flags & LFS_F_READING ) {
11881232 // just drop read cache
@@ -1225,9 +1269,21 @@ static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
12251269 }
12261270
12271271 // 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+ }
12311287 }
12321288
12331289 // actual file updates
@@ -1396,45 +1452,10 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
13961452
13971453 break ;
13981454relocate :
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 );
14041456 if (err ) {
14051457 return err ;
14061458 }
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 ;
14381459 }
14391460
14401461 file -> pos += diff ;
0 commit comments