Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
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
  • Loading branch information
geky committed Nov 20, 2020
commit 1ae4b36f2a717cd52601d10de6337f97bf4bcf50
18 changes: 11 additions & 7 deletions lfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
}
Expand Down Expand Up @@ -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;
Expand Down