@@ -452,14 +452,16 @@ static int lfs_alloc_lookahead(void *p, lfs_block_t block) {
452452 return 0 ;
453453}
454454
455+ // indicate allocated blocks have been committed into the filesystem, this
456+ // is to prevent blocks from being garbage collected in the middle of a
457+ // commit operation
455458static void lfs_alloc_ack (lfs_t * lfs ) {
456459 lfs -> free .ack = lfs -> cfg -> block_count ;
457460}
458461
459- // Invalidate the lookahead buffer. This is done during mounting and
460- // failed traversals
461- static void lfs_alloc_reset (lfs_t * lfs ) {
462- lfs -> free .off = lfs -> seed % lfs -> cfg -> block_size ;
462+ // drop the lookahead buffer, this is done during mounting and failed
463+ // traversals in order to avoid invalid lookahead state
464+ static void lfs_alloc_drop (lfs_t * lfs ) {
463465 lfs -> free .size = 0 ;
464466 lfs -> free .i = 0 ;
465467 lfs_alloc_ack (lfs );
@@ -505,7 +507,7 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
505507 memset (lfs -> free .buffer , 0 , lfs -> cfg -> lookahead_size );
506508 int err = lfs_fs_traverseraw (lfs , lfs_alloc_lookahead , lfs , true);
507509 if (err ) {
508- lfs_alloc_reset (lfs );
510+ lfs_alloc_drop (lfs );
509511 return err ;
510512 }
511513 }
@@ -870,8 +872,10 @@ static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs,
870872 ptag ^= (lfs_tag_t )(lfs_tag_chunk (tag ) & 1U ) << 31 ;
871873
872874 // toss our crc into the filesystem seed for
873- // pseudorandom numbers
874- lfs -> seed ^= crc ;
875+ // pseudorandom numbers, note we use another crc here
876+ // as a collection function because it is sufficiently
877+ // random and convenient
878+ lfs -> seed = lfs_crc (lfs -> seed , & crc , sizeof (crc ));
875879
876880 // update with what's found so far
877881 besttag = tempbesttag ;
@@ -1261,12 +1265,13 @@ static int lfs_dir_commitattr(lfs_t *lfs, struct lfs_commit *commit,
12611265}
12621266
12631267static int lfs_dir_commitcrc (lfs_t * lfs , struct lfs_commit * commit ) {
1264- const lfs_off_t off1 = commit -> off ;
1265- const uint32_t crc1 = commit -> crc ;
12661268 // align to program units
1267- const lfs_off_t end = lfs_alignup (off1 + 2 * sizeof (uint32_t ),
1269+ const lfs_off_t end = lfs_alignup (commit -> off + 2 * sizeof (uint32_t ),
12681270 lfs -> cfg -> prog_size );
12691271
1272+ lfs_off_t off1 = 0 ;
1273+ uint32_t crc1 = 0 ;
1274+
12701275 // create crc tags to fill up remainder of commit, note that
12711276 // padding is not crced, which lets fetches skip padding but
12721277 // makes committing a bit more complicated
@@ -1302,6 +1307,12 @@ static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) {
13021307 return err ;
13031308 }
13041309
1310+ // keep track of non-padding checksum to verify
1311+ if (off1 == 0 ) {
1312+ off1 = commit -> off + sizeof (uint32_t );
1313+ crc1 = commit -> crc ;
1314+ }
1315+
13051316 commit -> off += sizeof (tag )+ lfs_tag_size (tag );
13061317 commit -> ptag = tag ^ ((lfs_tag_t )reset << 31 );
13071318 commit -> crc = 0xffffffff ; // reset crc for next "commit"
@@ -1315,7 +1326,7 @@ static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) {
13151326
13161327 // successful commit, check checksums to make sure
13171328 lfs_off_t off = commit -> begin ;
1318- lfs_off_t noff = off1 + sizeof ( uint32_t ) ;
1329+ lfs_off_t noff = off1 ;
13191330 while (off < end ) {
13201331 uint32_t crc = 0xffffffff ;
13211332 for (lfs_off_t i = off ; i < noff + sizeof (uint32_t ); i ++ ) {
@@ -3797,8 +3808,10 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
37973808 lfs -> gstate .tag += !lfs_tag_isvalid (lfs -> gstate .tag );
37983809 lfs -> gdisk = lfs -> gstate ;
37993810
3800- // setup free lookahead
3801- lfs_alloc_reset (lfs );
3811+ // setup free lookahead, to distribute allocations uniformly across
3812+ // boots, we start the allocator at a random location
3813+ lfs -> free .off = lfs -> seed % lfs -> cfg -> block_count ;
3814+ lfs_alloc_drop (lfs );
38023815
38033816 LFS_TRACE ("lfs_mount -> %d" , 0 );
38043817 return 0 ;
0 commit comments