Quellcode durchsuchen

Fixed corner case in block_cycles eviction logic

The problem was when we allocate a dir-pair, it's possible for the
revision count to immediately overflow and the dir-pair be evicted and
returned to the unused blocks without being written even once. In the
case that block_cycles = 1, this made it impossible to ever create a
dir-pair, even in lfs_format.

I've also added a bit of logic to lfs_dir_alloc that will prevent
any immediate evictions because of the revision count.

found by TheLoneWolfling
Christopher Haster vor 6 Jahren
Ursprung
Commit
95c1a6339d
1 geänderte Dateien mit 5 neuen und 5 gelöschten Zeilen
  1. 5 5
      lfs.c

+ 5 - 5
lfs.c

@@ -1316,15 +1316,14 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) {
     int err = lfs_bd_read(lfs,
             NULL, &lfs->rcache, sizeof(dir->rev),
             dir->pair[0], 0, &dir->rev, sizeof(dir->rev));
-    if (err) {
-        return err;
-    }
-
     dir->rev = lfs_fromle32(dir->rev);
     if (err && err != LFS_ERR_CORRUPT) {
         return err;
     }
 
+    // make sure we don't immediately evict
+    dir->rev += dir->rev & 1;
+
     // set defaults
     dir->off = sizeof(dir->rev);
     dir->etag = 0xffffffff;
@@ -1457,7 +1456,8 @@ static int lfs_dir_compact(lfs_t *lfs,
 
     // increment revision count
     dir->rev += 1;
-    if (lfs->cfg->block_cycles && dir->rev % lfs->cfg->block_cycles == 0) {
+    if (lfs->cfg->block_cycles &&
+            (dir->rev % (lfs->cfg->block_cycles+1) == 0)) {
         if (lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0) {
             // oh no! we're writing too much to the superblock,
             // should we expand?