From 4fc03f95a76bf2759863592e8ee6338eb187bada Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 16 Jul 2024 17:04:53 -0500 Subject: [PATCH] Reworked lookahead buffer (again) to avoid shifting bits The main reason for this change is to allow keeping track of existing known-free blocks while trying to find more free blocks. This makes it so failed filesystem traversals don't result in negative progress, which is nice. This was difficult in the previous lookahead scheme, since we we'd need to shift the lookahead buffer to keep off=0 rooted at the first bit. Shifting bytes is relatively easily with memmove, but it gets tricky when shifting bits: lookahead before: ???? ???? ???? ??00 1101 0101 00?? ???? ^ ^ off off+size shift: 0011 0101 0100 ???? ???? ???? ???? ???? ^ ^ off off+size traverse: 0011 0101 0100 0000 0000 0000 1100 0000 ^ ^ off off+size Instead, we now just let the lookahead buffer wrap around. No shifting required: lookahead before: ???? ???? ???? ??00 1101 0101 00?? ???? ^ ^ off off+size traverse: 0000 0000 1100 0000 1101 0101 0000 0000 ^ off ^ off+size This gets a bit confusing with the lookahead window also wrapping around disk, but the math works out with enough modulos (if modulos are too expensive, we should eventually be able to optimize these into simple bit masks via compile-time config). In the future, if we move away from the const config struct, it would also be nice to try to reducing the number of modulos by storing the lookahead buffer size in bits instead of bytes... Note that if the lookahead buffer is larger than disk, the lookahead window will sort of travel around the underlying buffer. This isn't inherently a problem, but it did cause some bugs. To avoid similar bit-related problems with zeroing, lfs_alloc_inc now also zeros bits as we allocate/skip them, so bits should always be zero when we start a lookahead traversal. Though note we still need to manually memset the buffer when discarding lookahead state in init/grow. --- The end result is surprisingly a net savings in terms of code size. I guess mainly due to dropping all the lfs_alloc_shift calls: code stack before: 36472 2680 after: 36412 (-0.2%) 2680 (+0.0%) --- lfs.c | 145 ++++++++++++++------------- lfs.h | 4 +- tests/test_badblocks.toml | 12 +-- tests/test_btree.toml | 200 +++++++++++++++++++------------------- 4 files changed, 179 insertions(+), 182 deletions(-) diff --git a/lfs.c b/lfs.c index d07fb922..6c21d444 100644 --- a/lfs.c +++ b/lfs.c @@ -5934,7 +5934,9 @@ static bool lfsr_fs_isinconsistent(const lfs_t *lfs) { } static bool lfsr_fs_canlookahead(const lfs_t *lfs) { - return lfs->lookahead.next > 0 || lfs->lookahead.size == 0; + return lfs->lookahead.size < lfs_min( + 8*lfs->cfg->lookahead_size, + lfs->cfg->block_size); } @@ -8704,6 +8706,9 @@ static int lfsr_mtree_gc(lfs_t *lfs, lfsr_traversal_t *t, // swap dirty/mutated flags while in lfsr_mtree_gc t->o.o.flags = lfsr_f_swapdirty(t->o.o.flags); + // checkpoint the allocator to maximize any lookahead scans + lfs_alloc_ckpoint(lfs); + dropped:; lfsr_tag_t tag; lfsr_bptr_t bptr; @@ -8907,43 +8912,33 @@ static void lfs_alloc_ckpoint(lfs_t *lfs) { // discard any lookahead state, this is necessary if block_count changes static void lfs_alloc_discard(lfs_t *lfs) { - // go ahead shift to next available block, we probably want the next - // scan to start here - lfs->lookahead.start = (lfs->lookahead.start + lfs->lookahead.next) - % lfs->block_count; - lfs->lookahead.next = 0; lfs->lookahead.size = 0; -} - -// shift the lookahead buffer to try to allocate more blocks, may do nothing -static void lfs_alloc_shift(lfs_t *lfs) { - // do nothing if shifting would make no progress - if (lfs->lookahead.next > 0) { - // discard already shifts to the next block - lfs_alloc_discard(lfs); - } - - // zero lookahead buffer - if (lfs->lookahead.size == 0) { - lfs_memset(lfs->lookahead.buffer, 0, lfs->cfg->lookahead_size); - } - - // don't update size until a successful lookahead scan + lfs_memset(lfs->lookahead.buffer, 0, lfs->cfg->lookahead_size); } // mark a block as in-use static void lfs_alloc_markinuse(lfs_t *lfs, lfs_block_t block) { // translate to lookahead-relative - lfs_block_t mark = (block + lfs->block_count - lfs->lookahead.start) - % lfs->block_count; - if (mark < 8*lfs->cfg->lookahead_size) { + lfs_block_t block_ = (( + (lfs_sblock_t)(block + - (lfs->lookahead.window + lfs->lookahead.off)) + // we only need this mess because C's mod is actually rem, and + // we want real mod in case block_ goes negative + % (lfs_sblock_t)lfs->block_count) + + (lfs_sblock_t)lfs->block_count) + % (lfs_sblock_t)lfs->block_count; + + if (block_ < 8*lfs->cfg->lookahead_size) { // mark as in-use - lfs->lookahead.buffer[mark / 8] |= 1 << (mark % 8); + lfs->lookahead.buffer[ + ((lfs->lookahead.off + block_) / 8) + % lfs->cfg->lookahead_size] + |= 1 << ((lfs->lookahead.off + block_) % 8); } } // needed in lfs_alloc_markfree -static lfs_sblock_t lfs_alloc_findnext(lfs_t *lfs); +static lfs_sblock_t lfs_alloc_findfree(lfs_t *lfs); // mark any not-in-use blocks as free static void lfs_alloc_markfree(lfs_t *lfs) { @@ -8952,22 +8947,44 @@ static void lfs_alloc_markfree(lfs_t *lfs) { 8*lfs->cfg->lookahead_size, lfs->lookahead.ckpoint); - // eagerly find the next free block so shift can make progress - lfs_alloc_findnext(lfs); + // eagerly find the next free block so lookahead scans can make + // the most progress + lfs_alloc_findfree(lfs); +} + +// increment lookahead buffer +static void lfs_alloc_inc(lfs_t *lfs) { + LFS_ASSERT(lfs->lookahead.size > 0); + + // clear lookahead as we increment + lfs->lookahead.buffer[lfs->lookahead.off / 8] + &= ~(1 << (lfs->lookahead.off % 8)); + + // increment next/off + lfs->lookahead.off += 1; + if (lfs->lookahead.off == 8*lfs->cfg->lookahead_size) { + lfs->lookahead.off = 0; + lfs->lookahead.window = (lfs->lookahead.window + + 8*lfs->cfg->lookahead_size) + % lfs->block_count; + } + + // decrement size/ckpoint + lfs->lookahead.size -= 1; + lfs->lookahead.ckpoint -= 1; } // find next free block in lookahead buffer, if there is one -static lfs_sblock_t lfs_alloc_findnext(lfs_t *lfs) { - while (lfs->lookahead.next < lfs->lookahead.size) { - if (!(lfs->lookahead.buffer[lfs->lookahead.next / 8] - & (1 << (lfs->lookahead.next % 8)))) { +static lfs_sblock_t lfs_alloc_findfree(lfs_t *lfs) { + while (lfs->lookahead.size > 0) { + if (!(lfs->lookahead.buffer[lfs->lookahead.off / 8] + & (1 << (lfs->lookahead.off % 8)))) { // found a free block - return (lfs->lookahead.start + lfs->lookahead.next) + return (lfs->lookahead.window + lfs->lookahead.off) % lfs->block_count; } - lfs->lookahead.next += 1; - lfs->lookahead.ckpoint -= 1; + lfs_alloc_inc(lfs); } return LFS_ERR_NOSPC; @@ -8976,7 +8993,7 @@ static lfs_sblock_t lfs_alloc_findnext(lfs_t *lfs) { static lfs_sblock_t lfs_alloc(lfs_t *lfs, bool erase) { while (true) { // scan our lookahead buffer for free blocks - lfs_sblock_t block = lfs_alloc_findnext(lfs); + lfs_sblock_t block = lfs_alloc_findfree(lfs); if (block < 0 && block != LFS_ERR_NOSPC) { return block; } @@ -8991,8 +9008,7 @@ static lfs_sblock_t lfs_alloc(lfs_t *lfs, bool erase) { if (err) { // bad erase? try another block if (err == LFS_ERR_CORRUPT) { - lfs->lookahead.next += 1; - lfs->lookahead.ckpoint -= 1; + lfs_alloc_inc(lfs); continue; } return err; @@ -9001,33 +9017,31 @@ static lfs_sblock_t lfs_alloc(lfs_t *lfs, bool erase) { // eagerly find the next free block to maximize how many blocks // lfs_alloc_ckpoint makes available for scanning - lfs->lookahead.next += 1; - lfs->lookahead.ckpoint -= 1; - lfs_alloc_findnext(lfs); + lfs_alloc_inc(lfs); + lfs_alloc_findfree(lfs); return block; } - // In order to keep our block allocator from spinning forever when our + // in order to keep our block allocator from spinning forever when our // filesystem is full, we mark points where there are no in-flight - // allocations with a checkpoint before starting a set of allocations. + // allocations with a checkpoint before starting a set of allocations // - // If we've looked at all blocks since the last checkpoint, we report - // the filesystem as out of storage. + // if we've looked at all blocks since the last checkpoint, we report + // the filesystem as out of storage // if (lfs->lookahead.ckpoint <= 0) { - LFS_ERROR("No more free space 0x%"PRIx32, - (lfs->lookahead.start + lfs->lookahead.next) + LFS_ERROR("No more free space (0x%"PRIx32")", + (lfs->lookahead.window + lfs->lookahead.off) % lfs->block_count); return LFS_ERR_NOSPC; } - // no blocks in our lookahead buffer, we need to scan the filesystem - // for unused blocks in the next lookahead window - lfs_alloc_shift(lfs); - + // no blocks in our lookahead buffer? + // // traverse the filesystem, building up knowledge of what blocks are - // in use in our lookahead window + // in use in the next lookahead window + // lfsr_traversal_t t = LFSR_TRAVERSAL(LFS_T_LOOKAHEAD); while (true) { int err = lfsr_mtree_traverse(lfs, &t, @@ -11901,10 +11915,11 @@ static int lfs_init(lfs_t *lfs, uint32_t flags, goto failed; } } - lfs->lookahead.start = 0; + lfs->lookahead.window = 0; + lfs->lookahead.off = 0; lfs->lookahead.size = 0; - lfs->lookahead.next = 0; lfs->lookahead.ckpoint = 0; + lfs_alloc_discard(lfs); // check that the size limits are sane LFS_ASSERT(lfs->cfg->name_limit <= LFS_NAME_MAX); @@ -12551,7 +12566,7 @@ static int lfsr_mountinited(lfs_t *lfs) { // the purpose of this is to avoid bad wear patterns such as always // allocating blocks near the beginning of disk after a power-loss // - lfs->lookahead.start = lfs->seed % lfs->block_count; + lfs->lookahead.window = lfs->seed % lfs->block_count; // TODO should the consumegdelta above take gstate/gdelta as a parameter? // keep track of the current gstate on disk @@ -12687,12 +12702,6 @@ int lfsr_mount(lfs_t *lfs, uint32_t flags, lfsr_traversal_t t = LFSR_TRAVERSAL(flags_); lfsr_omdir_open(lfs, &t.o.o); - // shift the lookahead buffer if requested - if (lfsr_t_islookahead(t.o.o.flags)) { - lfs_alloc_shift(lfs); - lfs_alloc_ckpoint(lfs); - } - while (true) { err = lfsr_mtree_gc(lfs, &t, NULL, NULL); @@ -13133,12 +13142,6 @@ int lfsr_fs_gc(lfs_t *lfs, uint32_t flags) { } else { lfs->gc = LFSR_TRAVERSAL(flags); lfsr_omdir_open(lfs, &lfs->gc.o.o); - - // shift the lookahead buffer if requested - if (lfsr_t_islookahead(lfs->gc.o.o.flags)) { - lfs_alloc_shift(lfs); - lfs_alloc_ckpoint(lfs); - } } for (uint32_t i = 0; @@ -13385,12 +13388,6 @@ static int lfsr_traversal_rewind_(lfs_t *lfs, lfsr_traversal_t *t) { t->blocks[0] = -1; t->blocks[1] = -1; - // shift the lookahead buffer if requested - if (lfsr_t_islookahead(t->o.o.flags)) { - lfs_alloc_shift(lfs); - lfs_alloc_ckpoint(lfs); - } - return 0; } diff --git a/lfs.h b/lfs.h index 6be979e5..c055f52e 100644 --- a/lfs.h +++ b/lfs.h @@ -764,9 +764,9 @@ typedef struct lfs { } pcache; struct lfs_lookahead { - lfs_block_t start; + lfs_block_t window; + lfs_block_t off; lfs_block_t size; - lfs_block_t next; lfs_block_t ckpoint; uint8_t *buffer; } lookahead; diff --git a/tests/test_badblocks.toml b/tests/test_badblocks.toml index 978bb1b6..208dad1f 100644 --- a/tests/test_badblocks.toml +++ b/tests/test_badblocks.toml @@ -52,10 +52,10 @@ code = ''' CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -1787,10 +1787,10 @@ code = ''' CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -3522,10 +3522,10 @@ code = ''' CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree diff --git a/tests/test_btree.toml b/tests/test_btree.toml index 85ee0d30..aed49bcb 100644 --- a/tests/test_btree.toml +++ b/tests/test_btree.toml @@ -13,10 +13,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create an empty tree @@ -44,10 +44,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a single-entry tree @@ -85,10 +85,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a two-entry tree @@ -134,10 +134,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a two-entry tree @@ -184,10 +184,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a two-entry tree @@ -242,10 +242,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a two-entry tree @@ -303,10 +303,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree with N elements @@ -353,10 +353,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree with N elements @@ -405,10 +405,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -487,10 +487,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree with N elements @@ -555,10 +555,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -690,10 +690,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a single-entry tree @@ -735,10 +735,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a two-entry tree @@ -793,10 +793,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a two-entry tree @@ -865,10 +865,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree with N elements @@ -922,10 +922,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -1008,10 +1008,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree with N elements @@ -1081,10 +1081,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -1224,10 +1224,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a single-entry tree @@ -1280,10 +1280,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a single-entry tree @@ -1352,10 +1352,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a single-entry tree @@ -1424,10 +1424,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a single-entry tree @@ -1515,10 +1515,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree with N elements @@ -1594,10 +1594,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree with N elements @@ -1676,10 +1676,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -1764,10 +1764,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree with N elements @@ -1870,10 +1870,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -2020,10 +2020,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree with N elements @@ -2079,10 +2079,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -2168,10 +2168,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree with N elements @@ -2228,10 +2228,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -2404,10 +2404,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree @@ -2471,10 +2471,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree @@ -2541,10 +2541,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree @@ -2604,10 +2604,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree @@ -2684,10 +2684,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -2790,10 +2790,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -2956,10 +2956,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a zero-entry tree @@ -2989,10 +2989,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a single-entry tree @@ -3041,10 +3041,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a two-entry tree @@ -3107,10 +3107,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a two-entry tree @@ -3187,10 +3187,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a two-entry tree @@ -3268,10 +3268,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree with N elements @@ -3341,10 +3341,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -3455,10 +3455,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree with N elements @@ -3529,10 +3529,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -3685,10 +3685,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -3842,10 +3842,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree @@ -4047,10 +4047,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a tree with N elements @@ -4170,10 +4170,10 @@ code = ''' lfs_init(&lfs, LFS_M_RDWR, CFG) => 0; // create free lookahead memset(lfs.lookahead.buffer, 0, CFG->lookahead_size); - lfs.lookahead.start = 2; + lfs.lookahead.window = 2; + lfs.lookahead.off = 0; lfs.lookahead.size = lfs_min(8*CFG->lookahead_size, CFG->block_count-2); - lfs.lookahead.next = 2; lfs_alloc_ckpoint(&lfs); // create a btree