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.
This commit is contained in:
Christopher Haster
2024-05-14 13:27:33 -05:00
parent 11c948678f
commit 186fd1b5f2
9 changed files with 414 additions and 368 deletions
+166 -150
View File
@@ -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);
}
+49 -25
View File
@@ -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];
+18 -15
View File
@@ -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, \
+9 -6
View File
@@ -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, \
+6 -6
View File
@@ -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',
+42 -42
View File
@@ -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',
+38 -38
View File
@@ -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',
+40 -40
View File
@@ -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',
+46 -46
View File
@@ -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',