From 186fd1b5f2148969c1d5e14efc59af40fb4e314d Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 14 May 2024 13:27:33 -0500 Subject: [PATCH] Separated cache_size out into rcache_size/pcache_size/fbuffer_size A much requested feature, this allows much finer control of how RAM is allocated for the system. It was difficult to introduce this in previous versions of littlefs due to how we steal caches during certain file operations, but now we don't do that and treat the caches much more transparently. Managing separate cache sizes does add a bit of code, but this is well worth the potential for RAM savings due to increased flexibility: code stack before: 33656 2632 after: 33714 (+0.2%) 2640 (+0.3%) Also interesting to note this reduces alignment requirements for the rcache/pcache, since they don't need to share alignment, and completely removes any alignment requirement from the file buffers. --- lfs.c | 316 +++++++++++++++++++++------------------- lfs.h | 74 ++++++---- runners/bench_runner.h | 33 +++-- runners/test_runner.h | 15 +- tests/test_alloc.toml | 12 +- tests/test_files.toml | 84 +++++------ tests/test_forphan.toml | 76 +++++----- tests/test_fsync.toml | 80 +++++----- tests/test_fwrite.toml | 92 ++++++------ 9 files changed, 414 insertions(+), 368 deletions(-) diff --git a/lfs.c b/lfs.c index 5ecf7f9c..b55ca1a8 100644 --- a/lfs.c +++ b/lfs.c @@ -101,8 +101,12 @@ static int lfsr_bd_sync__(lfs_t *lfs) { /// Caching block device operations /// -static inline void lfsr_cache_drop(lfs_cache_t *cache) { - cache->size = 0; +static inline void lfsr_bd_droprcache(lfs_t *lfs) { + lfs->rcache.size = 0; +} + +static inline void lfsr_bd_droppcache(lfs_t *lfs) { + lfs->pcache.size = 0; } static int lfsr_bd_read_(lfs_t *lfs, lfs_block_t block, lfs_size_t off, @@ -193,7 +197,7 @@ static int lfsr_bd_readnext(lfs_t *lfs, } // drop rcache in case read fails - lfsr_cache_drop(&lfs->rcache); + lfsr_bd_droprcache(lfs); // load to cache, first condition can no longer fail lfs_size_t off__ = lfs_aligndown(off, lfs->cfg->read_size); @@ -202,7 +206,7 @@ static int lfsr_bd_readnext(lfs_t *lfs, (off-off__) + lfs_min( lfs_max(size, hint), lfs_min( - lfs->cfg->cache_size - (off-off__), + lfs->cfg->rcache_size - (off-off__), lfs->cfg->block_size - off)), lfs->cfg->read_size); int err = lfsr_bd_read_(lfs, block, off__, @@ -304,7 +308,7 @@ static int lfsr_bd_flush(lfs_t *lfs, uint32_t *cksum_) { } // make this cache available - lfsr_cache_drop(&lfs->pcache); + lfsr_bd_droppcache(lfs); } return 0; @@ -323,7 +327,7 @@ static int lfsr_bd_prognext(lfs_t *lfs, lfs_block_t block, lfs_size_t off, // need to flush pcache? if (!(block == lfs->pcache.block && off >= lfs->pcache.off - && off < lfs->pcache.off + lfs->cfg->cache_size)) { + && off < lfs->pcache.off + lfs->cfg->pcache_size)) { int err = lfsr_bd_flush(lfs, cksum_); if (err) { return err; @@ -344,12 +348,12 @@ static int lfsr_bd_prognext(lfs_t *lfs, lfs_block_t block, lfs_size_t off, lfs->pcache.size, lfs_min( (off-lfs->pcache.off) + size, - lfs->cfg->cache_size)); + lfs->cfg->pcache_size)); *buffer_ = &lfs->pcache.buffer[off-lfs->pcache.off]; *size_ = lfs_min( size, - lfs->cfg->cache_size - (off-lfs->pcache.off)); + lfs->cfg->pcache_size - (off-lfs->pcache.off)); return 0; } @@ -375,7 +379,7 @@ static int lfsr_bd_prog(lfs_t *lfs, lfs_block_t block, lfs_size_t off, // pcache takes priority && !(block == lfs->pcache.block && off_ >= lfs->pcache.off - && off_ < lfs->pcache.off + lfs->cfg->cache_size)) { + && off_ < lfs->pcache.off + lfs->cfg->pcache_size)) { // make sure we flush our pcache first, some devices // don't support out-of-order progs in a block if (lfs->pcache.size != 0) { @@ -465,10 +469,10 @@ static int lfsr_bd_erase(lfs_t *lfs, lfs_block_t block) { // make sure we invalidate any caches if (lfs->pcache.block == block) { - lfsr_cache_drop(&lfs->pcache); + lfsr_bd_droppcache(lfs); } if (lfs->rcache.block == block) { - lfsr_cache_drop(&lfs->rcache); + lfsr_bd_droprcache(lfs); } return lfsr_bd_erase__(lfs, block); @@ -9678,9 +9682,26 @@ static inline bool lfsr_f_iszombie(uint32_t flags) { return flags & LFS_F_ZOMBIE; } +// other file helpers +static inline lfs_size_t lfsr_file_buffersize(lfs_t *lfs, + const lfsr_file_t *file) { + return (file->cfg->buffer_size) + ? file->cfg->buffer_size + : lfs->cfg->fbuffer_size; +} + +static inline lfs_size_t lfsr_file_inlinesize(lfs_t *lfs, + const lfsr_file_t *file) { + return lfs_min32( + lfsr_file_buffersize(lfs, file), + lfs_min32( + lfs->cfg->inline_size, + lfs->cfg->fragment_size)); +} + static inline lfs_off_t lfsr_file_size_(const lfsr_file_t *file) { return lfs_max32( - file->buffer_pos + file->buffer_size, + file->buffer.pos + file->buffer.size, lfsr_bshrub_size(&file->bshrub)); } @@ -9822,22 +9843,20 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file, // allocate buffer if necessary if (file->cfg->buffer) { - file->buffer = file->cfg->buffer; + file->buffer.buffer = file->cfg->buffer; } else { - file->buffer = lfs_malloc(lfs->cfg->cache_size); - if (!file->buffer) { + file->buffer.buffer = lfs_malloc(lfsr_file_buffersize(lfs, file)); + if (!file->buffer.buffer) { return LFS_ERR_NOMEM; } } - file->buffer_pos = 0; - file->buffer_size = 0; + file->buffer.pos = 0; + file->buffer.size = 0; // if our file is small, try to keep the whole thing in our buffer - if (lfsr_bshrub_size(&file->bshrub) <= lfs->cfg->cache_size - && lfsr_bshrub_size(&file->bshrub) <= lfs->cfg->inline_size - && lfsr_bshrub_size(&file->bshrub) <= lfs->cfg->fragment_size) { + if (lfsr_bshrub_size(&file->bshrub) <= lfsr_file_inlinesize(lfs, file)) { lfs_ssize_t d = lfsr_bshrub_read(lfs, file, - 0, file->buffer, lfsr_bshrub_size(&file->bshrub)); + 0, file->buffer.buffer, lfsr_bshrub_size(&file->bshrub)); if (d < 0) { err = d; goto failed; @@ -9845,8 +9864,8 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file, // small files remain perpetually unflushed file->m.flags |= LFS_F_UNFLUSH; - file->buffer_pos = 0; - file->buffer_size = lfsr_bshrub_size(&file->bshrub); + file->buffer.pos = 0; + file->buffer.size = lfsr_bshrub_size(&file->bshrub); file->bshrub = LFSR_BSHRUB_BNULL(); } @@ -9857,7 +9876,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file, failed:; // clean up memory if (!file->cfg->buffer) { - lfs_free(file->buffer); + lfs_free(file->buffer.buffer); } return err; @@ -9887,7 +9906,7 @@ int lfsr_file_close(lfs_t *lfs, lfsr_file_t *file) { // clean up memory if (!file->cfg->buffer) { - lfs_free(file->buffer); + lfs_free(file->buffer.buffer); } // are we orphaning a file? @@ -11095,14 +11114,14 @@ lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file, lfs_ssize_t d = lfs_min32(size, lfsr_file_size_(file) - pos_); // any data in our buffer? - if (pos_ < file->buffer_pos + file->buffer_size - && file->buffer_size != 0) { - if (pos_ >= file->buffer_pos) { + if (pos_ < file->buffer.pos + file->buffer.size + && file->buffer.size != 0) { + if (pos_ >= file->buffer.pos) { lfs_ssize_t d_ = lfs_min32( d, - file->buffer_size - (pos_ - file->buffer_pos)); + file->buffer.size - (pos_ - file->buffer.pos)); memcpy(buffer_, - &file->buffer[pos_ - file->buffer_pos], + &file->buffer.buffer[pos_ - file->buffer.pos], d_); pos_ += d_; @@ -11113,13 +11132,13 @@ lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file, } // buffered data takes priority - d = lfs_min32(d, file->buffer_pos - pos_); + d = lfs_min32(d, file->buffer.pos - pos_); } // any data in our btree? if (pos_ < lfsr_bshrub_size(&file->bshrub)) { // bypass buffer? - if ((lfs_size_t)d >= lfs->cfg->cache_size) { + if ((lfs_size_t)d >= lfsr_file_buffersize(lfs, file)) { lfs_ssize_t d_ = lfsr_bshrub_readnext(lfs, file, pos_, buffer_, d); if (d_ < 0) { @@ -11143,19 +11162,19 @@ lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file, if (err) { return err; } - file->buffer_pos = 0; - file->buffer_size = 0; + file->buffer.pos = 0; + file->buffer.size = 0; } // try to fill our buffer with some data lfs_ssize_t d_ = lfsr_bshrub_readnext(lfs, file, - pos_, file->buffer, d); + pos_, file->buffer.buffer, d); if (d_ < 0) { LFS_ASSERT(d != LFS_ERR_NOENT); return d_; } - file->buffer_pos = pos_; - file->buffer_size = d_; + file->buffer.pos = pos_; + file->buffer.size = d_; continue; } @@ -11203,15 +11222,13 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file, // if we're a small file, we may need to append zeros if (pos > lfsr_file_size_(file) - && pos <= lfs->cfg->cache_size - && pos <= lfs->cfg->inline_size - && pos <= lfs->cfg->fragment_size) { + && pos <= lfsr_file_inlinesize(lfs, file)) { LFS_ASSERT(lfsr_f_isunflush(file->m.flags)); - LFS_ASSERT(lfsr_file_size_(file) == file->buffer_size); - memset(&file->buffer[file->buffer_size], + LFS_ASSERT(lfsr_file_size_(file) == file->buffer.size); + memset(&file->buffer.buffer[file->buffer.size], 0, - pos - file->buffer_size); - file->buffer_size = pos; + pos - file->buffer.size); + file->buffer.size = pos; } const uint8_t *buffer_ = buffer; @@ -11224,7 +11241,7 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file, // and avoids weird cases with low-level write heuristics // if (!lfsr_f_isunflush(file->m.flags) - && size >= lfs->cfg->cache_size) { + && size >= lfsr_file_buffersize(lfs, file)) { err = lfsr_file_flush_(lfs, file, pos, buffer_, size); if (err) { @@ -11235,11 +11252,11 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file, // // note we need to clear the buffer anyways to avoid any // out-of-date data - file->buffer_pos = pos + size - lfs->cfg->cache_size; - memcpy(file->buffer, - &buffer_[size - lfs->cfg->cache_size], - lfs->cfg->cache_size); - file->buffer_size = lfs->cfg->cache_size; + file->buffer.pos = pos + size - lfsr_file_buffersize(lfs, file); + memcpy(file->buffer.buffer, + &buffer_[size - lfsr_file_buffersize(lfs, file)], + lfsr_file_buffersize(lfs, file)); + file->buffer.size = lfsr_file_buffersize(lfs, file); written += size; pos += size; @@ -11259,22 +11276,25 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file, // buffer once, and flush at most twice. // if (!lfsr_f_isunflush(file->m.flags) - || (pos >= file->buffer_pos - && pos <= file->buffer_pos + file->buffer_size - && pos < file->buffer_pos + lfs->cfg->cache_size)) { + || (pos >= file->buffer.pos + && pos <= file->buffer.pos + file->buffer.size + && pos + < file->buffer.pos + + lfsr_file_buffersize(lfs, file))) { // unused buffer? we can move it where we need it if (!lfsr_f_isunflush(file->m.flags)) { - file->buffer_pos = pos; - file->buffer_size = 0; + file->buffer.pos = pos; + file->buffer.size = 0; } lfs_size_t d = lfs_min32( size, - lfs->cfg->cache_size - (pos - file->buffer_pos)); - memcpy(&file->buffer[pos - file->buffer_pos], buffer_, d); - file->buffer_size = lfs_max32( - file->buffer_size, - pos+d - file->buffer_pos); + lfsr_file_buffersize(lfs, file) + - (pos - file->buffer.pos)); + memcpy(&file->buffer.buffer[pos - file->buffer.pos], buffer_, d); + file->buffer.size = lfs_max32( + file->buffer.size, + pos+d - file->buffer.pos); file->m.flags |= LFS_F_UNFLUSH; written += d; @@ -11286,7 +11306,7 @@ lfs_ssize_t lfsr_file_write(lfs_t *lfs, lfsr_file_t *file, // flush our buffer so the above can't fail err = lfsr_file_flush_(lfs, file, - file->buffer_pos, file->buffer, file->buffer_size); + file->buffer.pos, file->buffer.buffer, file->buffer.size); if (err) { goto failed; } @@ -11329,9 +11349,7 @@ int lfsr_file_flush(lfs_t *lfs, lfsr_file_t *file) { // readonly files should do nothing LFS_ASSERT(!lfsr_o_isrdonly(file->m.flags) || !lfsr_f_isunflush(file->m.flags) - || (lfsr_file_size_(file) <= lfs->cfg->cache_size - && lfsr_file_size_(file) <= lfs->cfg->inline_size - && lfsr_file_size_(file) <= lfs->cfg->fragment_size)); + || lfsr_file_size_(file) <= lfsr_file_inlinesize(lfs, file)); // do nothing if our file is already flushed if (!lfsr_f_isunflush(file->m.flags)) { @@ -11341,11 +11359,9 @@ int lfsr_file_flush(lfs_t *lfs, lfsr_file_t *file) { // do nothing if our file is small // // note this means small files remain perpetually unflushed - if (lfsr_file_size_(file) <= lfs->cfg->cache_size - && lfsr_file_size_(file) <= lfs->cfg->inline_size - && lfsr_file_size_(file) <= lfs->cfg->fragment_size) { + if (lfsr_file_size_(file) <= lfsr_file_inlinesize(lfs, file)) { // our file must reside entirely in our buffer - LFS_ASSERT(file->buffer_pos == 0); + LFS_ASSERT(file->buffer.pos == 0); return 0; } @@ -11355,10 +11371,10 @@ int lfsr_file_flush(lfs_t *lfs, lfsr_file_t *file) { // flush our buffer if it contains any unwritten data if (lfsr_f_isunflush(file->m.flags) - && file->buffer_size != 0) { + && file->buffer.size != 0) { // flush err = lfsr_file_flush_(lfs, file, - file->buffer_pos, file->buffer, file->buffer_size); + file->buffer.pos, file->buffer.buffer, file->buffer.size); if (err) { goto failed; } @@ -11401,15 +11417,13 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) { LFS_ASSERT(!lfsr_bshrub_isbptr(&file->m.mdir, &file->bshrub)); // small files should start as zero, const prop should optimize this out LFS_ASSERT(!lfsr_f_isunflush(file->m.flags) - || file->buffer_pos == 0); + || file->buffer.pos == 0); // small files/btree should be exclusive here LFS_ASSERT(!lfsr_f_isunflush(file->m.flags) || lfsr_bshrub_size(&file->bshrub) == 0); // small files must be inlined entirely in our buffer LFS_ASSERT(!lfsr_f_isunflush(file->m.flags) - || (file->buffer_size <= lfs->cfg->cache_size - && file->buffer_size <= lfs->cfg->inline_size - && file->buffer_size <= lfs->cfg->fragment_size)); + || file->buffer.size <= lfsr_file_inlinesize(lfs, file)); // uncreat files must be unsync LFS_ASSERT(!lfsr_f_isorphan(file->m.flags) || lfsr_f_isunsync(file->m.flags)); @@ -11461,13 +11475,13 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) { // commit the file state // null? no attr? - if (lfsr_f_isunflush(file->m.flags) && file->buffer_size == 0) { + if (lfsr_f_isunflush(file->m.flags) && file->buffer.size == 0) { attrs[attr_count++] = LFSR_ATTR( LFSR_TAG_RM | LFSR_TAG_SUB | LFSR_TAG_STRUCT, 0, LFSR_DATA_NULL()); // small file inlined in mdir? } else if (lfsr_f_isunflush(file->m.flags)) { - data.data = LFSR_DATA_BUF(file->buffer, file->buffer_size); + data.data = LFSR_DATA_BUF(file->buffer.buffer, file->buffer.size); attrs[attr_count++] = LFSR_ATTR_CAT_( LFSR_TAG_SUB | LFSR_TAG_DATA, 0, &data.data, 1); @@ -11517,10 +11531,13 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) { file_->m.flags &= ~LFS_F_UNFLUSH; } file_->bshrub = file->bshrub; - file_->buffer_pos = file->buffer_pos; - LFS_ASSERT(file->buffer_size <= lfs->cfg->cache_size); - memcpy(file_->buffer, file->buffer, file->buffer_size); - file_->buffer_size = file->buffer_size; + file_->buffer.pos = file->buffer.pos; + LFS_ASSERT(file->buffer.size + <= lfsr_file_buffersize(lfs, file)); + memcpy(file_->buffer.buffer, + file->buffer.buffer, + file->buffer.size); + file_->buffer.size = file->buffer.size; } } } @@ -11599,43 +11616,41 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) { int err; // does our file become small? - if (size_ <= lfs->cfg->cache_size - && size_ <= lfs->cfg->inline_size - && size_ <= lfs->cfg->fragment_size) { + if (size_ <= lfsr_file_inlinesize(lfs, file)) { // if our data is not already in our buffer we unfortunately // need to flush so our buffer is available to hold everything - if (file->buffer_pos > 0 - || file->buffer_size < lfs_min32( + if (file->buffer.pos > 0 + || file->buffer.size < lfs_min32( size_, lfsr_bshrub_size(&file->bshrub))) { err = lfsr_file_flush(lfs, file); if (err) { goto failed; } - file->buffer_pos = 0; - file->buffer_size = 0; + file->buffer.pos = 0; + file->buffer.size = 0; lfs_ssize_t d = lfsr_bshrub_read(lfs, file, - 0, file->buffer, size_); + 0, file->buffer.buffer, size_); if (d < 0) { err = d; goto failed; } - file->buffer_pos = 0; - file->buffer_size = size_; + file->buffer.pos = 0; + file->buffer.size = size_; } // we may need to zero some of our buffer - if (size_ > file->buffer_size) { - memset(&file->buffer[file->buffer_size], + if (size_ > file->buffer.size) { + memset(&file->buffer.buffer[file->buffer.size], 0, - size_ - file->buffer_size); + size_ - file->buffer.size); } // small files remain perpetually unflushed file->m.flags |= LFS_F_UNFLUSH; - file->buffer_pos = 0; - file->buffer_size = size_; + file->buffer.pos = 0; + file->buffer.size = size_; file->bshrub = LFSR_BSHRUB_BNULL(); // truncate our file normally @@ -11651,10 +11666,10 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) { } // truncate our buffer - file->buffer_pos = lfs_min32(file->buffer_pos, size_); - file->buffer_size = lfs_min32( - file->buffer_size, - size_ - lfs_min32(file->buffer_pos, size_)); + file->buffer.pos = lfs_min32(file->buffer.pos, size_); + file->buffer.size = lfs_min32( + file->buffer.size, + size_ - lfs_min32(file->buffer.pos, size_)); } // mark as unsynced @@ -11704,56 +11719,54 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) { int err; // does our file become small? - if (size_ <= lfs->cfg->cache_size - && size_ <= lfs->cfg->inline_size - && size_ <= lfs->cfg->fragment_size) { + if (size_ <= lfsr_file_inlinesize(lfs, file)) { // if our data is not already in our buffer we unfortunately // need to flush so our buffer is available to hold everything - if (file->buffer_pos + file->buffer_size + if (file->buffer.pos + file->buffer.size < lfsr_bshrub_size(&file->bshrub) - || file->buffer_size < lfs_min32( + || file->buffer.size < lfs_min32( size_, lfsr_bshrub_size(&file->bshrub))) { err = lfsr_file_flush(lfs, file); if (err) { goto failed; } - file->buffer_pos = 0; - file->buffer_size = 0; + file->buffer.pos = 0; + file->buffer.size = 0; lfs_ssize_t d = lfsr_bshrub_read(lfs, file, lfsr_bshrub_size(&file->bshrub) - lfs_min32( size_, lfsr_bshrub_size(&file->bshrub)), - file->buffer, size_); + file->buffer.buffer, size_); if (d < 0) { err = d; goto failed; } - file->buffer_pos = 0; - file->buffer_size = size_; + file->buffer.pos = 0; + file->buffer.size = size_; } // we may need to move the data in our buffer - if (file->buffer_size > size_) { - memmove(file->buffer, - &file->buffer[file->buffer_size - size_], - file->buffer_size); + if (file->buffer.size > size_) { + memmove(file->buffer.buffer, + &file->buffer.buffer[file->buffer.size - size_], + file->buffer.size); } // we may need to zero some of our buffer - if (size_ > file->buffer_size) { - memmove(&file->buffer[size_ - file->buffer_size], - file->buffer, - file->buffer_size); - memset(file->buffer, + if (size_ > file->buffer.size) { + memmove(&file->buffer.buffer[size_ - file->buffer.size], + file->buffer.buffer, + file->buffer.size); + memset(file->buffer.buffer, 0, - size_ - file->buffer_size); + size_ - file->buffer.size); } // small files remain perpetually unflushed file->m.flags |= LFS_F_UNFLUSH; - file->buffer_pos = 0; - file->buffer_size = size_; + file->buffer.pos = 0; + file->buffer.size = size_; file->bshrub = LFSR_BSHRUB_BNULL(); // fruncate our file normally @@ -11769,25 +11782,25 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) { } // fruncate our buffer - memmove(file->buffer, - &file->buffer[lfs_min32( + memmove(file->buffer.buffer, + &file->buffer.buffer[lfs_min32( lfs_smax32( - size - size_ - file->buffer_pos, + size - size_ - file->buffer.pos, 0), - file->buffer_size)], - file->buffer_size - lfs_min32( + file->buffer.size)], + file->buffer.size - lfs_min32( lfs_smax32( - size - size_ - file->buffer_pos, + size - size_ - file->buffer.pos, 0), - file->buffer_size)); - file->buffer_size -= lfs_min32( + file->buffer.size)); + file->buffer.size -= lfs_min32( lfs_smax32( - size - size_ - file->buffer_pos, + size - size_ - file->buffer.pos, 0), - file->buffer_size); - file->buffer_pos -= lfs_smin32( + file->buffer.size); + file->buffer.pos -= lfs_smin32( size - size_, - file->buffer_pos); + file->buffer.pos); } // mark as unsynced @@ -15204,20 +15217,23 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { // performing any arithmetic logics with them LFS_ASSERT(lfs->cfg->read_size != 0); LFS_ASSERT(lfs->cfg->prog_size != 0); - LFS_ASSERT(lfs->cfg->cache_size != 0); + LFS_ASSERT(lfs->cfg->rcache_size != 0); + LFS_ASSERT(lfs->cfg->pcache_size != 0); - // check that block size is a multiple of cache size is a multiple - // of prog and read sizes - LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->read_size == 0); - LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->prog_size == 0); - LFS_ASSERT(lfs->cfg->block_size % lfs->cfg->cache_size == 0); + // cache sizes must be a multiple of the operation size + LFS_ASSERT(lfs->cfg->rcache_size % lfs->cfg->read_size == 0); + LFS_ASSERT(lfs->cfg->pcache_size % lfs->cfg->prog_size == 0); + + // block_size must be a multiple of both prog/read size + LFS_ASSERT(lfs->cfg->block_size % lfs->cfg->read_size == 0); + LFS_ASSERT(lfs->cfg->block_size % lfs->cfg->prog_size == 0); // block_size is currently limited to 28-bits LFS_ASSERT(lfs->cfg->block_size <= 0x0fffffff); - // check that the block size is large enough to fit ctz pointers - LFS_ASSERT(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4)) - <= lfs->cfg->block_size); +// // check that the block size is large enough to fit ctz pointers +// LFS_ASSERT(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4)) +// <= lfs->cfg->block_size); // block_cycles = 0 is no longer supported. // @@ -15238,10 +15254,10 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { lfs->rcache.block = 0; lfs->rcache.off = 0; lfs->rcache.size = 0; - if (lfs->cfg->read_buffer) { - lfs->rcache.buffer = lfs->cfg->read_buffer; + if (lfs->cfg->rcache_buffer) { + lfs->rcache.buffer = lfs->cfg->rcache_buffer; } else { - lfs->rcache.buffer = lfs_malloc(lfs->cfg->cache_size); + lfs->rcache.buffer = lfs_malloc(lfs->cfg->rcache_size); if (!lfs->rcache.buffer) { err = LFS_ERR_NOMEM; goto failed; @@ -15252,10 +15268,10 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { lfs->pcache.block = 0; lfs->pcache.off = 0; lfs->pcache.size = 0; - if (lfs->cfg->prog_buffer) { - lfs->pcache.buffer = lfs->cfg->prog_buffer; + if (lfs->cfg->pcache_buffer) { + lfs->pcache.buffer = lfs->cfg->pcache_buffer; } else { - lfs->pcache.buffer = lfs_malloc(lfs->cfg->cache_size); + lfs->pcache.buffer = lfs_malloc(lfs->cfg->pcache_size); if (!lfs->pcache.buffer) { err = LFS_ERR_NOMEM; goto failed; @@ -15407,11 +15423,11 @@ failed:; static int lfs_deinit(lfs_t *lfs) { // free allocated memory - if (!lfs->cfg->read_buffer) { + if (!lfs->cfg->rcache_buffer) { lfs_free(lfs->rcache.buffer); } - if (!lfs->cfg->prog_buffer) { + if (!lfs->cfg->pcache_buffer) { lfs_free(lfs->pcache.buffer); } diff --git a/lfs.h b/lfs.h index b7e81b97..04d8eefb 100644 --- a/lfs.h +++ b/lfs.h @@ -190,18 +190,17 @@ struct lfs_config { int (*unlock)(const struct lfs_config *c); #endif - // Minimum size of a block read in bytes. All read operations will be a + // Minimum size of a read in bytes. All read operations will be a // multiple of this value. lfs_size_t read_size; - // Minimum size of a block program in bytes. All program operations will be - // a multiple of this value. + // Minimum size of a program in bytes. All program operations will be a + // multiple of this value. lfs_size_t prog_size; // Size of an erasable block in bytes. This does not impact ram consumption - // and may be larger than the physical erase size. However, non-inlined - // files take up at minimum one block. Must be a multiple of the read and - // program sizes. + // and may be larger than the physical erase size. Must be a multiple of + // the read and program sizes. lfs_size_t block_size; // Number of erasable blocks on the device. @@ -215,26 +214,34 @@ struct lfs_config { // Set to -1 to disable block-level wear-leveling. int32_t block_cycles; - // Size of block caches in bytes. Each cache buffers a portion of a block in - // RAM. The littlefs needs a read cache, a program cache, and one additional - // cache per file. Larger caches can improve performance by storing more - // data and reducing the number of disk accesses. Must be a multiple of the - // read and program sizes, and a factor of the block size. - lfs_size_t cache_size; + // Size of the read cache in bytes. Larger buffers can improve + // performance by storing more data and reducing the number of disk + // accesses. Must be a multiple of the read size. + lfs_size_t rcache_size; + + // Size of the program cache in bytes. Larger buffers can improve + // performance by storing more data and reducing the number of disk + // accesses. Must be a multiple of the program size. + lfs_size_t pcache_size; + + // Size of file buffers in bytes. In addition to filesystem-wide + // read/prog buffers, each file gets its own buffer to reduce disk + // accesses. + lfs_size_t fbuffer_size; // 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. - // By default lfs_malloc is used to allocate this buffer. - void *read_buffer; + // Optional statically allocated read buffer. Must be rcache_size. By + // default lfs_malloc is used to allocate this buffer. + void *rcache_buffer; - // Optional statically allocated program buffer. Must be cache_size. - // By default lfs_malloc is used to allocate this buffer. - void *prog_buffer; + // Optional statically allocated program buffer. Must be pcache_size. By + // default lfs_malloc is used to allocate this buffer. + void *pcache_buffer; // Optional statically allocated lookahead buffer. Must be lookahead_size. // By default lfs_malloc is used to allocate this buffer. @@ -329,10 +336,15 @@ struct lfs_attr { // Optional configuration provided during lfs_file_opencfg struct lfs_file_config { - // Optional statically allocated file buffer. Must be cache_size. + // Optional statically allocated file buffer. Must be buffer_size. // By default lfs_malloc is used to allocate this buffer. void *buffer; + // Size of the file buffer in bytes. In addition to filesystem-wide + // read/prog buffers, each file gets its own buffer to reduce disk + // accesses. Defaults to file_buffer_size. + lfs_size_t buffer_size; + // Optional list of custom attributes related to the file. If the file // is opened with read access, these attributes will be read from disk // during the open call. If the file is opened with write access, the @@ -507,9 +519,11 @@ typedef struct lfsr_file { lfsr_bshrub_t bshrub_; lfs_off_t pos; - lfs_off_t buffer_pos; - uint8_t *buffer; - lfs_size_t buffer_size; + struct { + lfs_off_t pos; + lfs_off_t size; + uint8_t *buffer; + } buffer; lfs_block_t eblock; lfs_size_t eoff; @@ -561,8 +575,18 @@ typedef struct lfsr_grm { // The littlefs filesystem type typedef struct lfs { - lfs_cache_t rcache; - lfs_cache_t pcache; + struct { + lfs_block_t block; + lfs_size_t off; + lfs_size_t size; + uint8_t *buffer; + } rcache; + struct { + lfs_block_t block; + lfs_size_t off; + lfs_size_t size; + uint8_t *buffer; + } pcache; uint32_t pcksum; lfs_block_t root[2]; diff --git a/runners/bench_runner.h b/runners/bench_runner.h index d91f8a78..dfafc8d1 100644 --- a/runners/bench_runner.h +++ b/runners/bench_runner.h @@ -109,19 +109,20 @@ void bench_permutation(size_t i, uint32_t *buffer, size_t size); // a few preconfigured defines that control how benches run #define BENCH_IMPLICIT_DEFINES \ - /* name value (overridable) */ \ + /* name value (overridable) */ \ BENCH_DEFINE(READ_SIZE, 1 ) \ BENCH_DEFINE(PROG_SIZE, 1 ) \ BENCH_DEFINE(BLOCK_SIZE, 4096 ) \ BENCH_DEFINE(BLOCK_COUNT, DISK_SIZE/BLOCK_SIZE ) \ BENCH_DEFINE(DISK_SIZE, 1024*1024 ) \ - BENCH_DEFINE(CACHE_SIZE, \ - lfs_max(16, lfs_max(READ_SIZE, PROG_SIZE))) \ + BENCH_DEFINE(RCACHE_SIZE, lfs_max(16, READ_SIZE) ) \ + BENCH_DEFINE(PCACHE_SIZE, lfs_max(16, PROG_SIZE) ) \ + BENCH_DEFINE(FBUFFER_SIZE, 16 ) \ + BENCH_DEFINE(LOOKAHEAD_SIZE, 16 ) \ BENCH_DEFINE(INLINE_SIZE, BLOCK_SIZE/4 ) \ BENCH_DEFINE(SHRUB_SIZE, INLINE_SIZE ) \ BENCH_DEFINE(FRAGMENT_SIZE, BLOCK_SIZE/8 ) \ BENCH_DEFINE(CRYSTAL_THRESH, BLOCK_SIZE/8 ) \ - BENCH_DEFINE(LOOKAHEAD_SIZE, 16 ) \ BENCH_DEFINE(BLOCK_CYCLES, -1 ) \ BENCH_DEFINE(ERASE_VALUE, 0xff ) \ BENCH_DEFINE(ERASE_CYCLES, 0 ) \ @@ -137,17 +138,19 @@ void bench_permutation(size_t i, uint32_t *buffer, size_t size); // map defines to cfg struct fields #define BENCH_CFG \ - .read_size = READ_SIZE, \ - .prog_size = PROG_SIZE, \ - .block_size = BLOCK_SIZE, \ - .block_count = BLOCK_COUNT, \ - .block_cycles = BLOCK_CYCLES, \ - .cache_size = CACHE_SIZE, \ - .inline_size = INLINE_SIZE, \ - .shrub_size = SHRUB_SIZE, \ - .fragment_size = FRAGMENT_SIZE, \ - .crystal_thresh = CRYSTAL_THRESH, \ - .lookahead_size = LOOKAHEAD_SIZE, + .read_size = READ_SIZE, \ + .prog_size = PROG_SIZE, \ + .block_size = BLOCK_SIZE, \ + .block_count = BLOCK_COUNT, \ + .block_cycles = BLOCK_CYCLES, \ + .rcache_size = RCACHE_SIZE, \ + .pcache_size = PCACHE_SIZE, \ + .fbuffer_size = FBUFFER_SIZE, \ + .lookahead_size = LOOKAHEAD_SIZE, \ + .inline_size = INLINE_SIZE, \ + .shrub_size = SHRUB_SIZE, \ + .fragment_size = FRAGMENT_SIZE, \ + .crystal_thresh = CRYSTAL_THRESH, #define BENCH_BDCFG \ .erase_value = ERASE_VALUE, \ diff --git a/runners/test_runner.h b/runners/test_runner.h index 2d6760c7..8b600d62 100644 --- a/runners/test_runner.h +++ b/runners/test_runner.h @@ -99,13 +99,14 @@ void test_permutation(size_t i, uint32_t *buffer, size_t size); TEST_DEFINE(BLOCK_SIZE, 4096 ) \ TEST_DEFINE(BLOCK_COUNT, DISK_SIZE/BLOCK_SIZE ) \ TEST_DEFINE(DISK_SIZE, 1024*1024 ) \ - TEST_DEFINE(CACHE_SIZE, \ - lfs_max(16, lfs_max(READ_SIZE, PROG_SIZE)) ) \ + TEST_DEFINE(RCACHE_SIZE, lfs_max(16, READ_SIZE) ) \ + TEST_DEFINE(PCACHE_SIZE, lfs_max(16, PROG_SIZE) ) \ + TEST_DEFINE(FBUFFER_SIZE, 16 ) \ + TEST_DEFINE(LOOKAHEAD_SIZE, 16 ) \ TEST_DEFINE(INLINE_SIZE, BLOCK_SIZE/4 ) \ TEST_DEFINE(SHRUB_SIZE, INLINE_SIZE ) \ TEST_DEFINE(FRAGMENT_SIZE, BLOCK_SIZE/8 ) \ TEST_DEFINE(CRYSTAL_THRESH, BLOCK_SIZE/8 ) \ - TEST_DEFINE(LOOKAHEAD_SIZE, 16 ) \ TEST_DEFINE(BLOCK_CYCLES, -1 ) \ TEST_DEFINE(ERASE_VALUE, 0xff ) \ TEST_DEFINE(ERASE_CYCLES, 0 ) \ @@ -126,12 +127,14 @@ void test_permutation(size_t i, uint32_t *buffer, size_t size); .block_size = BLOCK_SIZE, \ .block_count = BLOCK_COUNT, \ .block_cycles = BLOCK_CYCLES, \ - .cache_size = CACHE_SIZE, \ + .rcache_size = RCACHE_SIZE, \ + .pcache_size = PCACHE_SIZE, \ + .fbuffer_size = FBUFFER_SIZE, \ + .lookahead_size = LOOKAHEAD_SIZE, \ .inline_size = INLINE_SIZE, \ .shrub_size = SHRUB_SIZE, \ .fragment_size = FRAGMENT_SIZE, \ - .crystal_thresh = CRYSTAL_THRESH, \ - .lookahead_size = LOOKAHEAD_SIZE, + .crystal_thresh = CRYSTAL_THRESH, #define TEST_BDCFG \ .erase_value = ERASE_VALUE, \ diff --git a/tests/test_alloc.toml b/tests/test_alloc.toml index 2c1bf832..276f83c2 100644 --- a/tests/test_alloc.toml +++ b/tests/test_alloc.toml @@ -256,8 +256,8 @@ code = ''' defines.N = [1, 2, 4, 8, 16, 32, 64] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -422,8 +422,8 @@ code = ''' defines.N = [1, 2, 4, 8, 16, 32, 64] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -658,8 +658,8 @@ code = ''' [cases.test_alloc_nospc_files] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', diff --git a/tests/test_files.toml b/tests/test_files.toml index a78bee9c..d98e6136 100644 --- a/tests/test_files.toml +++ b/tests/test_files.toml @@ -590,22 +590,22 @@ code = ''' # try writing larger files # # note: -# - at 2*CACHE_SIZE we need a shrub +# - at 2*FBUFFER_SIZE we need a shrub # - at BLOCK_SIZE/2 we need a block pointer # - at 2*BLOCK_SIZE we need a btree # [cases.test_files_more] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] defines.REMOUNT = [false, true] -defines.CACHE_SIZE = 64 +defines.FBUFFER_SIZE = 64 code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -672,8 +672,8 @@ code = ''' defines.N = [1, 2, 4, 8, 16, 32, 64] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -764,8 +764,8 @@ defines.N = [1, 2, 4, 8, 16, 32, 64] defines.DENSITY = 2 defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -900,15 +900,15 @@ code = ''' [cases.test_files_rm] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] defines.REMOUNT = [false, true] -defines.CACHE_SIZE = 64 +defines.FBUFFER_SIZE = 64 code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -967,8 +967,8 @@ defines.N = [1, 2, 4, 8, 16, 32, 64] defines.REMAINING = [4, 1, 0] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1114,8 +1114,8 @@ defines.N = [1, 2, 4, 8, 16, 32, 64] defines.DENSITY = 2 defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1268,8 +1268,8 @@ code = ''' [cases.test_files_mv] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1277,7 +1277,7 @@ defines.SIZE = [ ] defines.N = [0, 128] defines.REMOUNT = [false, true] -defines.CACHE_SIZE = 64 +defines.FBUFFER_SIZE = 64 code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -1367,8 +1367,8 @@ code = ''' [cases.test_files_mv_replace] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1376,7 +1376,7 @@ defines.SIZE = [ ] defines.N = [0, 128] defines.REMOUNT = [false, true] -defines.CACHE_SIZE = 64 +defines.FBUFFER_SIZE = 64 code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -1476,15 +1476,15 @@ code = ''' [cases.test_files_mv_noop] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] defines.REMOUNT = [false, true] -defines.CACHE_SIZE = 64 +defines.FBUFFER_SIZE = 64 code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -1559,15 +1559,15 @@ code = ''' [cases.test_files_mv_not_file] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] defines.REMOUNT = [false, true] -defines.CACHE_SIZE = 64 +defines.FBUFFER_SIZE = 64 code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -1653,15 +1653,15 @@ code = ''' [cases.test_files_mv_not_dir] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] defines.REMOUNT = [false, true] -defines.CACHE_SIZE = 64 +defines.FBUFFER_SIZE = 64 code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -1747,15 +1747,15 @@ code = ''' [cases.test_files_mv_not_root] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] defines.REMOUNT = [false, true] -defines.CACHE_SIZE = 64 +defines.FBUFFER_SIZE = 64 code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -1830,15 +1830,15 @@ code = ''' [cases.test_files_mv_not_noent] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', '4*BLOCK_SIZE', ] defines.REMOUNT = [false, true] -defines.CACHE_SIZE = 64 +defines.FBUFFER_SIZE = 64 code = ''' lfs_t lfs; lfsr_format(&lfs, CFG) => 0; @@ -1914,8 +1914,8 @@ code = ''' defines.N = [1, 2, 4, 8, 16, 32, 64] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2050,8 +2050,8 @@ defines.N = [1, 2, 4, 8, 16, 32, 64] defines.DENSITY = 2 defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2244,8 +2244,8 @@ defines.N = [1, 2, 4, 8, 16, 32, 64] defines.DENSITY = 2 defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', diff --git a/tests/test_forphan.toml b/tests/test_forphan.toml index 70ee79e1..4867b65a 100644 --- a/tests/test_forphan.toml +++ b/tests/test_forphan.toml @@ -5,8 +5,8 @@ after = ['test_fwrite', 'test_fsync'] # Some specific tests [cases.test_forphan_create] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -205,8 +205,8 @@ code = ''' [cases.test_forphan_create_pl] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -282,8 +282,8 @@ code = ''' [cases.test_forphan_create_many_pl] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', ] defines.CHUNK = 8 defines.N = 128 @@ -369,8 +369,8 @@ code = ''' [cases.test_forphan_create_sync_wr] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -559,8 +559,8 @@ code = ''' [cases.test_forphan_create_sync_rw] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -748,8 +748,8 @@ code = ''' [cases.test_forphan_create_desync_wdwr] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1066,8 +1066,8 @@ code = ''' [cases.test_forphan_orphan] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1175,8 +1175,8 @@ code = ''' [cases.test_forphan_orphan_wdwr] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1454,8 +1454,8 @@ code = ''' defines.N = 'range(6)' defines.M = 'range(6)' defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2136,8 +2136,8 @@ code = ''' [cases.test_forphan_zombie] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2263,8 +2263,8 @@ code = ''' [cases.test_forphan_zombie_posthumous] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2390,8 +2390,8 @@ code = ''' [cases.test_forphan_zombie_rwrw] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2616,8 +2616,8 @@ code = ''' [cases.test_forphan_zombie_rwrw_posthumous] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2842,8 +2842,8 @@ code = ''' [cases.test_forphan_zombie_zombie_rwrwrw] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -3103,8 +3103,8 @@ code = ''' [cases.test_forphan_zombie_zombie_rwrwrw_posthumous] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -4396,8 +4396,8 @@ code = ''' # them here [cases.test_forphan_rename] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -4632,8 +4632,8 @@ code = ''' [cases.test_forphan_rename_postrename] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -4928,8 +4928,8 @@ code = ''' [cases.test_forphan_rename_rwrw] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -5273,8 +5273,8 @@ code = ''' [cases.test_forphan_rename_rwrw_postrename] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', diff --git a/tests/test_fsync.toml b/tests/test_fsync.toml index 83fcad29..6d765e20 100644 --- a/tests/test_fsync.toml +++ b/tests/test_fsync.toml @@ -487,8 +487,8 @@ code = ''' [cases.test_fsync_rrrr] defines.R = 4 defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -537,8 +537,8 @@ defines.R = 4 defines.SEED = 'range(20)' defines.N = 20 defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -600,8 +600,8 @@ defines.SYNC = [0, 1, 2] # FLUSH=2 => flush via LFS_O_FLUSH defines.FLUSH = [0, 1, 2] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -690,8 +690,8 @@ defines.FLUSH = [0, 1, 2] defines.SEED = 'range(20)' defines.N = 20 defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -791,8 +791,8 @@ defines.SYNC = [0, 1, 2] # FLUSH=2 => flush via LFS_O_FLUSH defines.FLUSH = [0, 1, 2] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -876,8 +876,8 @@ defines.FLUSH = [0, 1, 2] defines.SEED = 'range(20)' defines.N = 20 defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -967,8 +967,8 @@ defines.SYNC = [0, 1, 2] # FLUSH=2 => flush via LFS_O_FLUSH defines.FLUSH = [0, 1, 2] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1069,8 +1069,8 @@ defines.FLUSH = [0, 1, 2] defines.SEED = 'range(20)' defines.N = 20 defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1181,8 +1181,8 @@ defines.SYNC = [0, 1, 2] # FLUSH=2 => flush via LFS_O_FLUSH defines.FLUSH = [0, 1, 2] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1282,8 +1282,8 @@ defines.FLUSH = [0, 1, 2] defines.SEED = 'range(20)' defines.N = 20 defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1394,8 +1394,8 @@ defines.FLUSH = [0, 1, 2] defines.SEED = 'range(20)' defines.N = 40 defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1528,8 +1528,8 @@ defines.FLUSH = [0, 1, 2] defines.SEED = 'range(20)' defines.N = 40 defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2334,8 +2334,8 @@ defines.SYNC = [0, 1, 2] # FLUSH=2 => flush via LFS_O_FLUSH defines.FLUSH = [0, 1, 2] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2429,8 +2429,8 @@ defines.FLUSH = [0, 1, 2] defines.SEED = 'range(20)' defines.N = 20 defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2535,8 +2535,8 @@ defines.SYNC = [0, 1, 2] # FLUSH=2 => flush via LFS_O_FLUSH defines.FLUSH = [0, 1, 2] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2622,8 +2622,8 @@ defines.FLUSH = [0, 1, 2] defines.SEED = 'range(20)' defines.N = 20 defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2720,8 +2720,8 @@ defines.SYNC = [0, 1, 2] # FLUSH=2 => flush via LFS_O_FLUSH defines.FLUSH = [0, 1, 2] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2830,8 +2830,8 @@ defines.FLUSH = [0, 1, 2] defines.SEED = 'range(20)' defines.N = 20 defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2947,8 +2947,8 @@ defines.FLUSH = [0, 1, 2] defines.SEED = 'range(20)' defines.N = 40 defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -3096,8 +3096,8 @@ defines.FLUSH = [0, 1, 2] defines.SEED = 'range(20)' defines.N = 40 defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', diff --git a/tests/test_fwrite.toml b/tests/test_fwrite.toml index bb26d1e6..c243b676 100644 --- a/tests/test_fwrite.toml +++ b/tests/test_fwrite.toml @@ -17,8 +17,8 @@ defines.PROG_SIZE = [1, 16] [cases.test_fwrite_incr] defines.SIZE = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -116,8 +116,8 @@ code = ''' # write strategies [cases.test_fwrite_overwrite] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -294,8 +294,8 @@ code = ''' # similar to overwrite files, but without underlying data [cases.test_fwrite_holes] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -476,8 +476,8 @@ code = ''' [cases.test_fwrite_truncate] defines.FROM = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -485,8 +485,8 @@ defines.FROM = [ ] defines.TO = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -589,8 +589,8 @@ code = ''' [cases.test_fwrite_truncate_truncate] defines.FROM = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -598,8 +598,8 @@ defines.FROM = [ ] defines.AND = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -607,8 +607,8 @@ defines.AND = [ ] defines.TO = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -730,8 +730,8 @@ code = ''' [cases.test_fwrite_fruncate] defines.FROM = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -739,8 +739,8 @@ defines.FROM = [ ] defines.TO = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -847,8 +847,8 @@ code = ''' [cases.test_fwrite_fruncate_fruncate] defines.FROM = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -856,8 +856,8 @@ defines.FROM = [ ] defines.AND = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -865,8 +865,8 @@ defines.AND = [ ] defines.TO = [ '0', - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -995,8 +995,8 @@ code = ''' # writing any data structure backwards always reveals issues [cases.test_fwrite_reversed] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1126,8 +1126,8 @@ code = ''' # trigger compaction [cases.test_fwrite_overwrite_compaction] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1313,8 +1313,8 @@ code = ''' [cases.test_fwrite_hole_compaction] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1506,8 +1506,8 @@ code = ''' defines.N = 20 defines.SEED = 'range(10)' defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1646,8 +1646,8 @@ code = ''' defines.N = 20 defines.SEED = 'range(10)' defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1795,8 +1795,8 @@ defines.N = 20 defines.SEED = 'range(10)' defines.WHENCE = ['LFS_SEEK_SET', 'LFS_SEEK_CUR', 'LFS_SEEK_END'] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -1873,8 +1873,8 @@ defines.N = 10 defines.SEED = 'range(10)' defines.WHENCE = ['LFS_SEEK_SET', 'LFS_SEEK_CUR', 'LFS_SEEK_END'] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2013,8 +2013,8 @@ defines.N = 10 defines.SEED = 'range(10)' defines.WHENCE = ['LFS_SEEK_SET', 'LFS_SEEK_CUR', 'LFS_SEEK_END'] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2175,8 +2175,8 @@ code = ''' [cases.test_fwrite_seek_negative] defines.WHENCE = ['LFS_SEEK_SET', 'LFS_SEEK_CUR', 'LFS_SEEK_END'] defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE', @@ -2276,8 +2276,8 @@ code = ''' defines.N = 20 defines.SEED = 'range(10)' defines.SIZE = [ - 'CACHE_SIZE/2', - '2*CACHE_SIZE', + 'FBUFFER_SIZE/2', + '2*FBUFFER_SIZE', 'BLOCK_SIZE/2', 'BLOCK_SIZE', '2*BLOCK_SIZE',