From 7872918ec89b23324345fc486163bcc1898fba76 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 29 Jul 2019 01:34:23 -0500 Subject: [PATCH] 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. --- lfs.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lfs.c b/lfs.c index 0111a6c..e7c4dae 100644 --- a/lfs.c +++ b/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;