forked from Imagelibrary/littlefs
Compare commits
12 Commits
fix-pendin
...
v2.9.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68d28b5114 | ||
|
|
1bc14933b7 | ||
|
|
01b6a47ea8 | ||
|
|
749a45650f | ||
|
|
4dd30c1b8f | ||
|
|
5c0d332ecd | ||
|
|
cf68333a55 | ||
|
|
7873d811a0 | ||
|
|
fc2aa3350c | ||
|
|
6352185949 | ||
|
|
f2a6f45eef | ||
|
|
2752d8c486 |
@@ -258,6 +258,9 @@ License Identifiers that are here available: http://spdx.org/licenses/
|
||||
use with the MirageOS library operating system project. It is interoperable
|
||||
with the reference implementation, with some caveats.
|
||||
|
||||
- [nim-littlefs] - A Nim wrapper and API for littlefs. Includes a fuse
|
||||
implementation based on [littlefs-fuse]
|
||||
|
||||
[BSD-3-Clause]: https://spdx.org/licenses/BSD-3-Clause.html
|
||||
[littlefs-disk-img-viewer]: https://github.com/tniessen/littlefs-disk-img-viewer
|
||||
[littlefs-fuse]: https://github.com/geky/littlefs-fuse
|
||||
@@ -274,3 +277,4 @@ License Identifiers that are here available: http://spdx.org/licenses/
|
||||
[littlefs-python]: https://pypi.org/project/littlefs-python/
|
||||
[littlefs2-rust]: https://crates.io/crates/littlefs2
|
||||
[chamelon]: https://github.com/yomimono/chamelon
|
||||
[nim-littlefs]: https://github.com/Graveflo/nim-littlefs
|
||||
|
||||
108
bd/lfs_emubd.c
108
bd/lfs_emubd.c
@@ -129,6 +129,8 @@ int lfs_emubd_create(const struct lfs_config *cfg,
|
||||
bd->proged = 0;
|
||||
bd->erased = 0;
|
||||
bd->power_cycles = bd->cfg->power_cycles;
|
||||
bd->ooo_block = -1;
|
||||
bd->ooo_data = NULL;
|
||||
bd->disk = NULL;
|
||||
|
||||
if (bd->cfg->disk_path) {
|
||||
@@ -195,6 +197,7 @@ int lfs_emubd_destroy(const struct lfs_config *cfg) {
|
||||
free(bd->blocks);
|
||||
|
||||
// clean up other resources
|
||||
lfs_emubd_decblock(bd->ooo_data);
|
||||
if (bd->disk) {
|
||||
bd->disk->rc -= 1;
|
||||
if (bd->disk->rc == 0) {
|
||||
@@ -209,6 +212,75 @@ int lfs_emubd_destroy(const struct lfs_config *cfg) {
|
||||
}
|
||||
|
||||
|
||||
// powerloss hook
|
||||
static int lfs_emubd_powerloss(const struct lfs_config *cfg) {
|
||||
lfs_emubd_t *bd = cfg->context;
|
||||
|
||||
// emulate out-of-order writes?
|
||||
lfs_emubd_block_t *ooo_data = NULL;
|
||||
if (bd->cfg->powerloss_behavior == LFS_EMUBD_POWERLOSS_OOO
|
||||
&& bd->ooo_block != -1) {
|
||||
// since writes between syncs are allowed to be out-of-order, it
|
||||
// shouldn't hurt to restore the first write on powerloss, right?
|
||||
ooo_data = bd->blocks[bd->ooo_block];
|
||||
bd->blocks[bd->ooo_block] = lfs_emubd_incblock(bd->ooo_data);
|
||||
|
||||
// mirror to disk file?
|
||||
if (bd->disk
|
||||
&& (bd->blocks[bd->ooo_block]
|
||||
|| bd->cfg->erase_value != -1)) {
|
||||
off_t res1 = lseek(bd->disk->fd,
|
||||
(off_t)bd->ooo_block*bd->cfg->erase_size,
|
||||
SEEK_SET);
|
||||
if (res1 < 0) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
ssize_t res2 = write(bd->disk->fd,
|
||||
(bd->blocks[bd->ooo_block])
|
||||
? bd->blocks[bd->ooo_block]->data
|
||||
: bd->disk->scratch,
|
||||
bd->cfg->erase_size);
|
||||
if (res2 < 0) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// simulate power loss
|
||||
bd->cfg->powerloss_cb(bd->cfg->powerloss_data);
|
||||
|
||||
// if we continue, undo out-of-order write emulation
|
||||
if (bd->cfg->powerloss_behavior == LFS_EMUBD_POWERLOSS_OOO
|
||||
&& bd->ooo_block != -1) {
|
||||
lfs_emubd_decblock(bd->blocks[bd->ooo_block]);
|
||||
bd->blocks[bd->ooo_block] = ooo_data;
|
||||
|
||||
// mirror to disk file?
|
||||
if (bd->disk
|
||||
&& (bd->blocks[bd->ooo_block]
|
||||
|| bd->cfg->erase_value != -1)) {
|
||||
off_t res1 = lseek(bd->disk->fd,
|
||||
(off_t)bd->ooo_block*bd->cfg->erase_size,
|
||||
SEEK_SET);
|
||||
if (res1 < 0) {
|
||||
return -errno;
|
||||
}
|
||||
|
||||
ssize_t res2 = write(bd->disk->fd,
|
||||
(bd->blocks[bd->ooo_block])
|
||||
? bd->blocks[bd->ooo_block]->data
|
||||
: bd->disk->scratch,
|
||||
bd->cfg->erase_size);
|
||||
if (res2 < 0) {
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// block device API
|
||||
|
||||
@@ -344,8 +416,11 @@ int lfs_emubd_prog(const struct lfs_config *cfg, lfs_block_t block,
|
||||
if (bd->power_cycles > 0) {
|
||||
bd->power_cycles -= 1;
|
||||
if (bd->power_cycles == 0) {
|
||||
// simulate power loss
|
||||
bd->cfg->powerloss_cb(bd->cfg->powerloss_data);
|
||||
int err = lfs_emubd_powerloss(cfg);
|
||||
if (err) {
|
||||
LFS_EMUBD_TRACE("lfs_emubd_prog -> %d", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,10 +436,17 @@ int lfs_emubd_erase(const struct lfs_config *cfg, lfs_block_t block) {
|
||||
// check if erase is valid
|
||||
LFS_ASSERT(block < bd->cfg->erase_count);
|
||||
|
||||
// emulate out-of-order writes? save first write
|
||||
if (bd->cfg->powerloss_behavior == LFS_EMUBD_POWERLOSS_OOO
|
||||
&& bd->ooo_block == -1) {
|
||||
bd->ooo_block = block;
|
||||
bd->ooo_data = lfs_emubd_incblock(bd->blocks[block]);
|
||||
}
|
||||
|
||||
// get the block
|
||||
lfs_emubd_block_t *b = lfs_emubd_mutblock(cfg, &bd->blocks[block]);
|
||||
if (!b) {
|
||||
LFS_EMUBD_TRACE("lfs_emubd_prog -> %d", LFS_ERR_NOMEM);
|
||||
LFS_EMUBD_TRACE("lfs_emubd_erase -> %d", LFS_ERR_NOMEM);
|
||||
return LFS_ERR_NOMEM;
|
||||
}
|
||||
|
||||
@@ -430,8 +512,11 @@ int lfs_emubd_erase(const struct lfs_config *cfg, lfs_block_t block) {
|
||||
if (bd->power_cycles > 0) {
|
||||
bd->power_cycles -= 1;
|
||||
if (bd->power_cycles == 0) {
|
||||
// simulate power loss
|
||||
bd->cfg->powerloss_cb(bd->cfg->powerloss_data);
|
||||
int err = lfs_emubd_powerloss(cfg);
|
||||
if (err) {
|
||||
LFS_EMUBD_TRACE("lfs_emubd_erase -> %d", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,14 +526,21 @@ int lfs_emubd_erase(const struct lfs_config *cfg, lfs_block_t block) {
|
||||
|
||||
int lfs_emubd_sync(const struct lfs_config *cfg) {
|
||||
LFS_EMUBD_TRACE("lfs_emubd_sync(%p)", (void*)cfg);
|
||||
lfs_emubd_t *bd = cfg->context;
|
||||
|
||||
// do nothing
|
||||
(void)cfg;
|
||||
// emulate out-of-order writes? reset first write, writes
|
||||
// cannot be out-of-order across sync
|
||||
if (bd->cfg->powerloss_behavior == LFS_EMUBD_POWERLOSS_OOO) {
|
||||
lfs_emubd_decblock(bd->ooo_data);
|
||||
bd->ooo_block = -1;
|
||||
bd->ooo_data = NULL;
|
||||
}
|
||||
|
||||
LFS_EMUBD_TRACE("lfs_emubd_sync -> %d", 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// Additional extended API for driving test features ///
|
||||
|
||||
static int lfs_emubd_crc_(const struct lfs_config *cfg,
|
||||
@@ -633,6 +725,8 @@ int lfs_emubd_copy(const struct lfs_config *cfg, lfs_emubd_t *copy) {
|
||||
copy->proged = bd->proged;
|
||||
copy->erased = bd->erased;
|
||||
copy->power_cycles = bd->power_cycles;
|
||||
copy->ooo_block = bd->ooo_block;
|
||||
copy->ooo_data = lfs_emubd_incblock(bd->ooo_data);
|
||||
copy->disk = bd->disk;
|
||||
if (copy->disk) {
|
||||
copy->disk->rc += 1;
|
||||
|
||||
@@ -36,17 +36,18 @@ extern "C"
|
||||
// Not that read-noop is not allowed. Read _must_ return a consistent (but
|
||||
// may be arbitrary) value on every read.
|
||||
typedef enum lfs_emubd_badblock_behavior {
|
||||
LFS_EMUBD_BADBLOCK_PROGERROR,
|
||||
LFS_EMUBD_BADBLOCK_ERASEERROR,
|
||||
LFS_EMUBD_BADBLOCK_READERROR,
|
||||
LFS_EMUBD_BADBLOCK_PROGNOOP,
|
||||
LFS_EMUBD_BADBLOCK_ERASENOOP,
|
||||
LFS_EMUBD_BADBLOCK_PROGERROR = 0, // Error on prog
|
||||
LFS_EMUBD_BADBLOCK_ERASEERROR = 1, // Error on erase
|
||||
LFS_EMUBD_BADBLOCK_READERROR = 2, // Error on read
|
||||
LFS_EMUBD_BADBLOCK_PROGNOOP = 3, // Prog does nothing silently
|
||||
LFS_EMUBD_BADBLOCK_ERASENOOP = 4, // Erase does nothing silently
|
||||
} lfs_emubd_badblock_behavior_t;
|
||||
|
||||
// Mode determining how power-loss behaves during testing. For now this
|
||||
// only supports a noop behavior, leaving the data on-disk untouched.
|
||||
typedef enum lfs_emubd_powerloss_behavior {
|
||||
LFS_EMUBD_POWERLOSS_NOOP,
|
||||
LFS_EMUBD_POWERLOSS_NOOP = 0, // Progs are atomic
|
||||
LFS_EMUBD_POWERLOSS_OOO = 1, // Blocks are written out-of-order
|
||||
} lfs_emubd_powerloss_behavior_t;
|
||||
|
||||
// Type for measuring read/program/erase operations
|
||||
@@ -152,6 +153,8 @@ typedef struct lfs_emubd {
|
||||
lfs_emubd_io_t proged;
|
||||
lfs_emubd_io_t erased;
|
||||
lfs_emubd_powercycles_t power_cycles;
|
||||
lfs_ssize_t ooo_block;
|
||||
lfs_emubd_block_t *ooo_data;
|
||||
lfs_emubd_disk_t *disk;
|
||||
|
||||
const struct lfs_emubd_config *cfg;
|
||||
|
||||
11
lfs.c
11
lfs.c
@@ -688,7 +688,7 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
|
||||
if (lfs->lookahead.ckpoint <= 0) {
|
||||
LFS_ERROR("No more free space 0x%"PRIx32,
|
||||
(lfs->lookahead.start + lfs->lookahead.next)
|
||||
% lfs->cfg->block_count);
|
||||
% lfs->block_count);
|
||||
return LFS_ERR_NOSPC;
|
||||
}
|
||||
|
||||
@@ -3404,6 +3404,15 @@ static int lfs_file_sync_(lfs_t *lfs, lfs_file_t *file) {
|
||||
|
||||
if ((file->flags & LFS_F_DIRTY) &&
|
||||
!lfs_pair_isnull(file->m.pair)) {
|
||||
// before we commit metadata, we need sync the disk to make sure
|
||||
// data writes don't complete after metadata writes
|
||||
if (!(file->flags & LFS_F_INLINE)) {
|
||||
err = lfs_bd_sync(lfs, &lfs->pcache, &lfs->rcache, false);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
// update dir entry
|
||||
uint16_t type;
|
||||
const void *buffer;
|
||||
|
||||
16
lfs.h
16
lfs.h
@@ -59,7 +59,8 @@ typedef uint32_t lfs_block_t;
|
||||
#endif
|
||||
|
||||
// Maximum size of custom attributes in bytes, may be redefined, but there is
|
||||
// no real benefit to using a smaller LFS_ATTR_MAX. Limited to <= 1022.
|
||||
// no real benefit to using a smaller LFS_ATTR_MAX. Limited to <= 1022. Stored
|
||||
// in superblock and must be respected by other littlefs drivers.
|
||||
#ifndef LFS_ATTR_MAX
|
||||
#define LFS_ATTR_MAX 1022
|
||||
#endif
|
||||
@@ -203,7 +204,8 @@ struct lfs_config {
|
||||
// program sizes.
|
||||
lfs_size_t block_size;
|
||||
|
||||
// Number of erasable blocks on the device.
|
||||
// Number of erasable blocks on the device. Defaults to block_count stored
|
||||
// on disk when zero.
|
||||
lfs_size_t block_count;
|
||||
|
||||
// Number of erase cycles before littlefs evicts metadata logs and moves
|
||||
@@ -252,18 +254,18 @@ struct lfs_config {
|
||||
|
||||
// Optional upper limit on length of file names in bytes. No downside for
|
||||
// larger names except the size of the info struct which is controlled by
|
||||
// the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX when zero. Stored in
|
||||
// superblock and must be respected by other littlefs drivers.
|
||||
// the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX or name_max stored on
|
||||
// disk when zero.
|
||||
lfs_size_t name_max;
|
||||
|
||||
// Optional upper limit on files in bytes. No downside for larger files
|
||||
// but must be <= LFS_FILE_MAX. Defaults to LFS_FILE_MAX when zero. Stored
|
||||
// in superblock and must be respected by other littlefs drivers.
|
||||
// but must be <= LFS_FILE_MAX. Defaults to LFS_FILE_MAX or file_max stored
|
||||
// on disk when zero.
|
||||
lfs_size_t file_max;
|
||||
|
||||
// Optional upper limit on custom attributes in bytes. No downside for
|
||||
// larger attributes size but must be <= LFS_ATTR_MAX. Defaults to
|
||||
// LFS_ATTR_MAX when zero.
|
||||
// LFS_ATTR_MAX or attr_max stored on disk when zero.
|
||||
lfs_size_t attr_max;
|
||||
|
||||
// Optional upper limit on total space given to metadata pairs in bytes. On
|
||||
|
||||
@@ -8,17 +8,22 @@ defines.FILES = 3
|
||||
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)'
|
||||
defines.GC = [false, true]
|
||||
defines.COMPACT_THRESH = ['-1', '0', 'BLOCK_SIZE/2']
|
||||
defines.INFER_BC = [false, true]
|
||||
code = '''
|
||||
const char *names[] = {"bacon", "eggs", "pancakes"};
|
||||
lfs_file_t files[FILES];
|
||||
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
struct lfs_config cfg_ = *cfg;
|
||||
if (INFER_BC) {
|
||||
cfg_.block_count = 0;
|
||||
}
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
lfs_mkdir(&lfs, "breakfast") => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
@@ -39,7 +44,7 @@ code = '''
|
||||
}
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
@@ -62,17 +67,22 @@ defines.FILES = 3
|
||||
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)'
|
||||
defines.GC = [false, true]
|
||||
defines.COMPACT_THRESH = ['-1', '0', 'BLOCK_SIZE/2']
|
||||
defines.INFER_BC = [false, true]
|
||||
code = '''
|
||||
const char *names[] = {"bacon", "eggs", "pancakes"};
|
||||
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
struct lfs_config cfg_ = *cfg;
|
||||
if (INFER_BC) {
|
||||
cfg_.block_count = 0;
|
||||
}
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
lfs_mkdir(&lfs, "breakfast") => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
lfs_file_t file;
|
||||
@@ -91,7 +101,7 @@ code = '''
|
||||
lfs_unmount(&lfs) => 0;
|
||||
}
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
@@ -113,19 +123,24 @@ code = '''
|
||||
defines.FILES = 3
|
||||
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)'
|
||||
defines.CYCLES = [1, 10]
|
||||
defines.INFER_BC = [false, true]
|
||||
code = '''
|
||||
const char *names[] = {"bacon", "eggs", "pancakes"};
|
||||
lfs_file_t files[FILES];
|
||||
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
struct lfs_config cfg_ = *cfg;
|
||||
if (INFER_BC) {
|
||||
cfg_.block_count = 0;
|
||||
}
|
||||
|
||||
for (int c = 0; c < CYCLES; c++) {
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
lfs_mkdir(&lfs, "breakfast") => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
@@ -143,7 +158,7 @@ code = '''
|
||||
}
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
@@ -159,7 +174,7 @@ code = '''
|
||||
}
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
@@ -175,19 +190,24 @@ code = '''
|
||||
defines.FILES = 3
|
||||
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-6)) / FILES)'
|
||||
defines.CYCLES = [1, 10]
|
||||
defines.INFER_BC = [false, true]
|
||||
code = '''
|
||||
const char *names[] = {"bacon", "eggs", "pancakes"};
|
||||
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
struct lfs_config cfg_ = *cfg;
|
||||
if (INFER_BC) {
|
||||
cfg_.block_count = 0;
|
||||
}
|
||||
|
||||
for (int c = 0; c < CYCLES; c++) {
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
lfs_mkdir(&lfs, "breakfast") => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
for (int n = 0; n < FILES; n++) {
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
char path[1024];
|
||||
sprintf(path, "breakfast/%s", names[n]);
|
||||
lfs_file_t file;
|
||||
@@ -232,10 +252,15 @@ code = '''
|
||||
|
||||
# exhaustion test
|
||||
[cases.test_alloc_exhaustion]
|
||||
defines.INFER_BC = [false, true]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
struct lfs_config cfg_ = *cfg;
|
||||
if (INFER_BC) {
|
||||
cfg_.block_count = 0;
|
||||
}
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, "exhaustion", LFS_O_WRONLY | LFS_O_CREAT);
|
||||
size_t size = strlen("exhaustion");
|
||||
@@ -263,7 +288,7 @@ code = '''
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY);
|
||||
size = strlen("exhaustion");
|
||||
lfs_file_size(&lfs, &file) => size;
|
||||
@@ -276,10 +301,15 @@ code = '''
|
||||
# exhaustion wraparound test
|
||||
[cases.test_alloc_exhaustion_wraparound]
|
||||
defines.SIZE = '(((BLOCK_SIZE-8)*(BLOCK_COUNT-4)) / 3)'
|
||||
defines.INFER_BC = [false, true]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
struct lfs_config cfg_ = *cfg;
|
||||
if (INFER_BC) {
|
||||
cfg_.block_count = 0;
|
||||
}
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
|
||||
lfs_file_t file;
|
||||
lfs_file_open(&lfs, &file, "padding", LFS_O_WRONLY | LFS_O_CREAT);
|
||||
@@ -317,7 +347,7 @@ code = '''
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
lfs_file_open(&lfs, &file, "exhaustion", LFS_O_RDONLY);
|
||||
size = strlen("exhaustion");
|
||||
lfs_file_size(&lfs, &file) => size;
|
||||
@@ -330,10 +360,15 @@ code = '''
|
||||
|
||||
# dir exhaustion test
|
||||
[cases.test_alloc_dir_exhaustion]
|
||||
defines.INFER_BC = [false, true]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
lfs_mount(&lfs, cfg) => 0;
|
||||
struct lfs_config cfg_ = *cfg;
|
||||
if (INFER_BC) {
|
||||
cfg_.block_count = 0;
|
||||
}
|
||||
lfs_mount(&lfs, &cfg_) => 0;
|
||||
|
||||
// find out max file size
|
||||
lfs_mkdir(&lfs, "exhaustiondir") => 0;
|
||||
|
||||
@@ -181,6 +181,10 @@ code = '''
|
||||
defines.N = [5, 11]
|
||||
if = 'BLOCK_COUNT >= 4*N'
|
||||
reentrant = true
|
||||
defines.POWERLOSS_BEHAVIOR = [
|
||||
'LFS_EMUBD_POWERLOSS_NOOP',
|
||||
'LFS_EMUBD_POWERLOSS_OOO',
|
||||
]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
int err = lfs_mount(&lfs, cfg);
|
||||
@@ -439,6 +443,10 @@ code = '''
|
||||
defines.N = [5, 25]
|
||||
if = 'N < BLOCK_COUNT/2'
|
||||
reentrant = true
|
||||
defines.POWERLOSS_BEHAVIOR = [
|
||||
'LFS_EMUBD_POWERLOSS_NOOP',
|
||||
'LFS_EMUBD_POWERLOSS_OOO',
|
||||
]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
int err = lfs_mount(&lfs, cfg);
|
||||
|
||||
@@ -310,6 +310,10 @@ defines.SIZE = [32, 0, 7, 2049]
|
||||
defines.CHUNKSIZE = [31, 16, 65]
|
||||
defines.INLINE_MAX = [0, -1, 8]
|
||||
reentrant = true
|
||||
defines.POWERLOSS_BEHAVIOR = [
|
||||
'LFS_EMUBD_POWERLOSS_NOOP',
|
||||
'LFS_EMUBD_POWERLOSS_OOO',
|
||||
]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
int err = lfs_mount(&lfs, cfg);
|
||||
@@ -500,6 +504,10 @@ code = '''
|
||||
[cases.test_files_many_power_loss]
|
||||
defines.N = 300
|
||||
reentrant = true
|
||||
defines.POWERLOSS_BEHAVIOR = [
|
||||
'LFS_EMUBD_POWERLOSS_NOOP',
|
||||
'LFS_EMUBD_POWERLOSS_OOO',
|
||||
]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
int err = lfs_mount(&lfs, cfg);
|
||||
|
||||
@@ -195,6 +195,10 @@ code = '''
|
||||
defines.SIZE = [10, 100]
|
||||
defines.FILES = [4, 10, 26]
|
||||
reentrant = true
|
||||
defines.POWERLOSS_BEHAVIOR = [
|
||||
'LFS_EMUBD_POWERLOSS_NOOP',
|
||||
'LFS_EMUBD_POWERLOSS_OOO',
|
||||
]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_file_t files[FILES];
|
||||
|
||||
@@ -357,6 +357,10 @@ code = '''
|
||||
|
||||
[cases.test_move_reentrant_file]
|
||||
reentrant = true
|
||||
defines.POWERLOSS_BEHAVIOR = [
|
||||
'LFS_EMUBD_POWERLOSS_NOOP',
|
||||
'LFS_EMUBD_POWERLOSS_OOO',
|
||||
]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
int err = lfs_mount(&lfs, cfg);
|
||||
@@ -839,6 +843,10 @@ code = '''
|
||||
|
||||
[cases.test_reentrant_dir]
|
||||
reentrant = true
|
||||
defines.POWERLOSS_BEHAVIOR = [
|
||||
'LFS_EMUBD_POWERLOSS_NOOP',
|
||||
'LFS_EMUBD_POWERLOSS_OOO',
|
||||
]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
int err = lfs_mount(&lfs, cfg);
|
||||
|
||||
@@ -329,6 +329,10 @@ code = '''
|
||||
# must be power-of-2 for quadratic probing to be exhaustive
|
||||
defines.COUNT = [4, 64, 128]
|
||||
reentrant = true
|
||||
defines.POWERLOSS_BEHAVIOR = [
|
||||
'LFS_EMUBD_POWERLOSS_NOOP',
|
||||
'LFS_EMUBD_POWERLOSS_OOO',
|
||||
]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
int err = lfs_mount(&lfs, cfg);
|
||||
|
||||
@@ -32,6 +32,10 @@ code = '''
|
||||
# reentrant format
|
||||
[cases.test_superblocks_reentrant_format]
|
||||
reentrant = true
|
||||
defines.POWERLOSS_BEHAVIOR = [
|
||||
'LFS_EMUBD_POWERLOSS_NOOP',
|
||||
'LFS_EMUBD_POWERLOSS_OOO',
|
||||
]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
int err = lfs_mount(&lfs, cfg);
|
||||
@@ -174,6 +178,10 @@ code = '''
|
||||
defines.BLOCK_CYCLES = [2, 1]
|
||||
defines.N = 24
|
||||
reentrant = true
|
||||
defines.POWERLOSS_BEHAVIOR = [
|
||||
'LFS_EMUBD_POWERLOSS_NOOP',
|
||||
'LFS_EMUBD_POWERLOSS_OOO',
|
||||
]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
int err = lfs_mount(&lfs, cfg);
|
||||
|
||||
@@ -231,6 +231,10 @@ defines.SMALLSIZE = [4, 512]
|
||||
defines.MEDIUMSIZE = [0, 3, 4, 5, 31, 32, 33, 511, 512, 513, 1023, 1024, 1025]
|
||||
defines.LARGESIZE = 2048
|
||||
reentrant = true
|
||||
defines.POWERLOSS_BEHAVIOR = [
|
||||
'LFS_EMUBD_POWERLOSS_NOOP',
|
||||
'LFS_EMUBD_POWERLOSS_OOO',
|
||||
]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
int err = lfs_mount(&lfs, cfg);
|
||||
|
||||
Reference in New Issue
Block a user