浏览代码

Fixed issue where lfs_migrate would relocate root and corrupt superblock

Found during testing, the issue was with lfs_migrate in combination with
wear leveling.

Normally, we can expect lfs_migrate to be able to respect the user-configured
block_cycles. It already has allocation information on which blocks are
used by both v1 and v2, so it should be safe to relocate blocks as
needed.

However, this fell apart when root was relocated. If lfs_migrate found a
root that needed migration, it would happily relocate the root. This
would normally be fine, except relocating the root has a side-effect of
needed to update the superblock. Which, during migration, is in a
delicate state of containing both v1's and v2's superblocks in the same
metadata pair. If the superblock ends up needing to compact, this would
clobber the v1 superblock and corrupt the filesystem during migration.

The best fix I could come up with is to specifically dissallow migrating the
root directory during migration. Fortunately this is behind the
LFS_MIGRATE macro, so the code cost for this check is not normally paid.
Christopher Haster 6 年之前
父节点
当前提交
7872918ec8
共有 1 个文件被更改,包括 5 次插入0 次删除
  1. 5 0
      lfs.c

+ 5 - 0
lfs.c

@@ -1500,6 +1500,11 @@ static int lfs_dir_compact(lfs_t *lfs,
                     end = begin;
                 }
             }
+#if LFS_MIGRATE
+        } else if (lfs_pair_cmp(dir->pair, lfs->root) == 0 && lfs->lfs1) {
+            // we can't relocate our root during migrations, as this would
+            // cause the superblock to get updated, which would clobber v1
+#endif
         } else {
             // we're writing too much, time to relocate
             exhausted = true;