Skip to content

Commit

Permalink
Relaxed lookahead buffer alignment
Browse files Browse the repository at this point in the history
This drops the lookahead buffer from operating on 32-bit words to
operating on 8-bit bytes, and removes any alignment requirement. This
may have some minor performance impact, but it is unlikely to be
significant when you consider IO overhead.

The original motivation for 32-bit alignment was an attempt at
future-proofing in case we wanted some more complex on-disk data
structure. This never happened, and even if it did, it could have been
added via additional config options.

This has been a significant pain point for users, since providing
word-aligned byte-sized buffers in C can be a bit annoying.
  • Loading branch information
geky committed Dec 20, 2023
1 parent 1f9c3c0 commit b1b10c0
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 13 deletions.
15 changes: 7 additions & 8 deletions lfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ static int lfs_alloc_lookahead(void *p, lfs_block_t block) {
+ lfs->block_count) % lfs->block_count;

if (off < lfs->lookahead.size) {
lfs->lookahead.buffer[off / 32] |= 1U << (off % 32);
lfs->lookahead.buffer[off / 8] |= 1U << (off % 8);
}

return 0;
Expand Down Expand Up @@ -653,8 +653,8 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
while (true) {
// scan our lookahead buffer for free blocks
while (lfs->lookahead.next < lfs->lookahead.size) {
if (!(lfs->lookahead.buffer[lfs->lookahead.next / 32]
& (1U << (lfs->lookahead.next % 32)))) {
if (!(lfs->lookahead.buffer[lfs->lookahead.next / 8]
& (1U << (lfs->lookahead.next % 8)))) {
// found a free block
*block = (lfs->lookahead.start + lfs->lookahead.next)
% lfs->block_count;
Expand All @@ -666,8 +666,8 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
lfs->lookahead.ckpoint -= 1;

if (lfs->lookahead.next >= lfs->lookahead.size
|| !(lfs->lookahead.buffer[lfs->lookahead.next / 32]
& (1U << (lfs->lookahead.next % 32)))) {
|| !(lfs->lookahead.buffer[lfs->lookahead.next / 8]
& (1U << (lfs->lookahead.next % 8)))) {
return 0;
}
}
Expand Down Expand Up @@ -4199,10 +4199,9 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
lfs_cache_zero(lfs, &lfs->rcache);
lfs_cache_zero(lfs, &lfs->pcache);

// setup lookahead, must be multiple of 64-bits, 32-bit aligned
// setup lookahead buffer, note mount finishes initializing this after
// we establish a decent pseudo-random seed
LFS_ASSERT(lfs->cfg->lookahead_size > 0);
LFS_ASSERT(lfs->cfg->lookahead_size % 8 == 0 &&
(uintptr_t)lfs->cfg->lookahead_buffer % 4 == 0);
if (lfs->cfg->lookahead_buffer) {
lfs->lookahead.buffer = lfs->cfg->lookahead_buffer;
} else {
Expand Down
9 changes: 4 additions & 5 deletions lfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ struct lfs_config {
// Size of the lookahead buffer in bytes. A larger lookahead buffer
// increases the number of blocks found during an allocation pass. The
// lookahead buffer is stored as a compact bitmap, so each byte of RAM
// can track 8 blocks. Must be a multiple of 8.
// can track 8 blocks.
lfs_size_t lookahead_size;

// Optional statically allocated read buffer. Must be cache_size.
Expand All @@ -237,9 +237,8 @@ struct lfs_config {
// By default lfs_malloc is used to allocate this buffer.
void *prog_buffer;

// Optional statically allocated lookahead buffer. Must be lookahead_size
// and aligned to a 32-bit boundary. By default lfs_malloc is used to
// allocate this buffer.
// Optional statically allocated lookahead buffer. Must be lookahead_size.
// By default lfs_malloc is used to allocate this buffer.
void *lookahead_buffer;

// Optional upper limit on length of file names in bytes. No downside for
Expand Down Expand Up @@ -435,7 +434,7 @@ typedef struct lfs {
lfs_block_t size;
lfs_block_t next;
lfs_block_t ckpoint;
uint32_t *buffer;
uint8_t *buffer;
} lookahead;

const struct lfs_config *cfg;
Expand Down

0 comments on commit b1b10c0

Please sign in to comment.