From 1ae4b36f2a717cd52601d10de6337f97bf4bcf50 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Fri, 20 Nov 2020 00:18:13 -0600 Subject: [PATCH] Removed unnecessary randomization of offsets in lfs_alloc_reset On first read, randomizing the allocators offset may seem appropriate for lfs_alloc_reset. However, it ends up using the filesystem-fed pseudorandom seed in situations it wasn't designed for. As noted by gtaska, the combination of using xors for feeding the seed and multiple traverses of the same CRCs can cause the seed to flip to zeros with concerning frequency. Removed the randomization from lfs_alloc_reset, leaving it in only lfs_mount. Found by gtaska --- lfs.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/lfs.c b/lfs.c index 7f99ccb..cc8ca38 100644 --- a/lfs.c +++ b/lfs.c @@ -452,14 +452,16 @@ static int lfs_alloc_lookahead(void *p, lfs_block_t block) { return 0; } +// indicate allocated blocks have been committed into the filesystem, this +// is to prevent blocks from being garbage collected in the middle of a +// commit operation static void lfs_alloc_ack(lfs_t *lfs) { lfs->free.ack = lfs->cfg->block_count; } -// Invalidate the lookahead buffer. This is done during mounting and -// failed traversals -static void lfs_alloc_reset(lfs_t *lfs) { - lfs->free.off = lfs->seed % lfs->cfg->block_count; +// drop the lookahead buffer, this is done during mounting and failed +// traversals in order to avoid invalid lookahead state +static void lfs_alloc_drop(lfs_t *lfs) { lfs->free.size = 0; lfs->free.i = 0; lfs_alloc_ack(lfs); @@ -505,7 +507,7 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) { memset(lfs->free.buffer, 0, lfs->cfg->lookahead_size); int err = lfs_fs_traverseraw(lfs, lfs_alloc_lookahead, lfs, true); if (err) { - lfs_alloc_reset(lfs); + lfs_alloc_drop(lfs); return err; } } @@ -3797,8 +3799,10 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) { lfs->gstate.tag += !lfs_tag_isvalid(lfs->gstate.tag); lfs->gdisk = lfs->gstate; - // setup free lookahead - lfs_alloc_reset(lfs); + // setup free lookahead, to distribute allocations uniformly across + // boots, we start the allocator at a random location + lfs->free.off = lfs->seed % lfs->cfg->block_count; + lfs_alloc_drop(lfs); LFS_TRACE("lfs_mount -> %d", 0); return 0;