t: Added lookahead to lfsr_traversal_t, adopted in lfs_alloc

This sort of turned into a complete refactor of lfs_alloc in order to
move/reuse the lookahead buffer filling logic into lfsr_fs_traverse.

lfs_alloc now calls lfsr_fs_traverse to fill the lookahead buffer when
no more blocks are available, but also you can too with lfsr_traversal_t
+ LFS_T_LOOKAHEAD.

The one big caveat being if any mutation happens to the filesystem, any
incomplete lookahead needs to be tossed out. To help with this,
lfsr_traversal_read now returns LFS_ERR_BUSY (-16) instead of
LFS_ERR_NOENT (-2) if the filesystem has been modified since the
traversal was opened.

Note that by default lfsr_traversal_t will still try to keep traversing
blocks, but can be told to terminate immediately with LFS_T_EXCL.
Continuing the traversal is probably desired for checking checksums,
debugging, etc, as otherwise you could end up looping over only the
first couple blocks in a write-heavy system, but if you are trying to
populate the lookahead buffer you probably want to just abort and start
over.

I considered adding a flags field to lfs_tinfo for this, but decided
against it since it would be the only place in the current API where we
don't use error codes to convey behavior-changing information. Though
this may be worth reconsidering at some point...

---

In reworking lfs_alloc, a lot of the internal logic was broken up into
specific functions:

- lfs_alloc_ckpoint - checkpoint the allocator
- lfs_alloc_discard - discard any lookahead
- lfs_alloc_shift - discard/shift lookahead if progress can be made
- lfs_alloc_markinuse - mark a block as in-use
- lfs_alloc_markfree - mark any remaining blocks as free
- lfs_alloc_findnext - find the next free block in lookahead

If anything this probably makes lfs_alloc more readable, though the
original motivation was to allow lfsr_traversal_t to only shift/zero the
lookahead buffer if there's a chance we can make progress.

This was based on upstream work by opilat and myself.

Code changes:

           code          stack
  before: 34226           2560
  after:  34474 (+0.7%)   2552 (-0.3%)
This commit is contained in:
Christopher Haster
2024-06-14 20:44:01 -05:00
parent 670b9fbf99
commit 635e1fe8d4
5 changed files with 2396 additions and 252 deletions
+9 -12
View File
@@ -27,11 +27,10 @@ code = '''
lfs_alloc_ckpoint(&lfs);
lfs_size_t alloced = 0;
while (true) {
lfs_block_t block;
int err = lfs_alloc(&lfs, &block, ERASE);
assert(!err || err == LFS_ERR_NOSPC);
lfs_sblock_t block = lfs_alloc(&lfs, ERASE);
assert(block >= 0 || block == LFS_ERR_NOSPC);
if (err == LFS_ERR_NOSPC) {
if (block == LFS_ERR_NOSPC) {
break;
}
alloced += 1;
@@ -61,11 +60,10 @@ code = '''
lfs_alloc_ckpoint(&lfs);
lfs_size_t alloced = 0;
while (true) {
lfs_block_t block;
int err = lfs_alloc(&lfs, &block, ERASE);
assert(!err || err == LFS_ERR_NOSPC);
lfs_sblock_t block = lfs_alloc(&lfs, ERASE);
assert(block >= 0 || block == LFS_ERR_NOSPC);
if (err == LFS_ERR_NOSPC) {
if (block == LFS_ERR_NOSPC) {
break;
}
alloced += 1;
@@ -83,11 +81,10 @@ code = '''
lfs_alloc_ckpoint(&lfs);
alloced = 0;
while (true) {
lfs_block_t block;
int err = lfs_alloc(&lfs, &block, ERASE);
assert(!err || err == LFS_ERR_NOSPC);
lfs_sblock_t block = lfs_alloc(&lfs, ERASE);
assert(block >= 0 || block == LFS_ERR_NOSPC);
if (err == LFS_ERR_NOSPC) {
if (block == LFS_ERR_NOSPC) {
break;
}
alloced += 1;
+2101 -45
View File
File diff suppressed because it is too large Load Diff