Generated v2 prefixes

This commit is contained in:
geky-bot
2024-03-08 23:23:45 +00:00
11 changed files with 174 additions and 17 deletions
+4
View File
@@ -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 use with the MirageOS library operating system project. It is interoperable
with the reference implementation, with some caveats. 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 [BSD-3-Clause]: https://spdx.org/licenses/BSD-3-Clause.html
[littlefs-disk-img-viewer]: https://github.com/tniessen/littlefs-disk-img-viewer [littlefs-disk-img-viewer]: https://github.com/tniessen/littlefs-disk-img-viewer
[littlefs-fuse]: https://github.com/geky/littlefs-fuse [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/ [littlefs-python]: https://pypi.org/project/littlefs-python/
[littlefs2-rust]: https://crates.io/crates/littlefs2 [littlefs2-rust]: https://crates.io/crates/littlefs2
[chamelon]: https://github.com/yomimono/chamelon [chamelon]: https://github.com/yomimono/chamelon
[nim-littlefs]: https://github.com/Graveflo/nim-littlefs
+101 -7
View File
@@ -129,6 +129,8 @@ int lfs2_emubd_create(const struct lfs2_config *cfg,
bd->proged = 0; bd->proged = 0;
bd->erased = 0; bd->erased = 0;
bd->power_cycles = bd->cfg->power_cycles; bd->power_cycles = bd->cfg->power_cycles;
bd->ooo_block = -1;
bd->ooo_data = NULL;
bd->disk = NULL; bd->disk = NULL;
if (bd->cfg->disk_path) { if (bd->cfg->disk_path) {
@@ -195,6 +197,7 @@ int lfs2_emubd_destroy(const struct lfs2_config *cfg) {
free(bd->blocks); free(bd->blocks);
// clean up other resources // clean up other resources
lfs2_emubd_decblock(bd->ooo_data);
if (bd->disk) { if (bd->disk) {
bd->disk->rc -= 1; bd->disk->rc -= 1;
if (bd->disk->rc == 0) { if (bd->disk->rc == 0) {
@@ -209,6 +212,75 @@ int lfs2_emubd_destroy(const struct lfs2_config *cfg) {
} }
// powerloss hook
static int lfs2_emubd_powerloss(const struct lfs2_config *cfg) {
lfs2_emubd_t *bd = cfg->context;
// emulate out-of-order writes?
lfs2_emubd_block_t *ooo_data = NULL;
if (bd->cfg->powerloss_behavior == LFS2_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] = lfs2_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 == LFS2_EMUBD_POWERLOSS_OOO
&& bd->ooo_block != -1) {
lfs2_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 // block device API
@@ -344,8 +416,11 @@ int lfs2_emubd_prog(const struct lfs2_config *cfg, lfs2_block_t block,
if (bd->power_cycles > 0) { if (bd->power_cycles > 0) {
bd->power_cycles -= 1; bd->power_cycles -= 1;
if (bd->power_cycles == 0) { if (bd->power_cycles == 0) {
// simulate power loss int err = lfs2_emubd_powerloss(cfg);
bd->cfg->powerloss_cb(bd->cfg->powerloss_data); if (err) {
LFS2_EMUBD_TRACE("lfs2_emubd_prog -> %d", err);
return err;
}
} }
} }
@@ -361,10 +436,17 @@ int lfs2_emubd_erase(const struct lfs2_config *cfg, lfs2_block_t block) {
// check if erase is valid // check if erase is valid
LFS2_ASSERT(block < bd->cfg->erase_count); LFS2_ASSERT(block < bd->cfg->erase_count);
// emulate out-of-order writes? save first write
if (bd->cfg->powerloss_behavior == LFS2_EMUBD_POWERLOSS_OOO
&& bd->ooo_block == -1) {
bd->ooo_block = block;
bd->ooo_data = lfs2_emubd_incblock(bd->blocks[block]);
}
// get the block // get the block
lfs2_emubd_block_t *b = lfs2_emubd_mutblock(cfg, &bd->blocks[block]); lfs2_emubd_block_t *b = lfs2_emubd_mutblock(cfg, &bd->blocks[block]);
if (!b) { if (!b) {
LFS2_EMUBD_TRACE("lfs2_emubd_prog -> %d", LFS2_ERR_NOMEM); LFS2_EMUBD_TRACE("lfs2_emubd_erase -> %d", LFS2_ERR_NOMEM);
return LFS2_ERR_NOMEM; return LFS2_ERR_NOMEM;
} }
@@ -430,8 +512,11 @@ int lfs2_emubd_erase(const struct lfs2_config *cfg, lfs2_block_t block) {
if (bd->power_cycles > 0) { if (bd->power_cycles > 0) {
bd->power_cycles -= 1; bd->power_cycles -= 1;
if (bd->power_cycles == 0) { if (bd->power_cycles == 0) {
// simulate power loss int err = lfs2_emubd_powerloss(cfg);
bd->cfg->powerloss_cb(bd->cfg->powerloss_data); if (err) {
LFS2_EMUBD_TRACE("lfs2_emubd_erase -> %d", err);
return err;
}
} }
} }
@@ -441,14 +526,21 @@ int lfs2_emubd_erase(const struct lfs2_config *cfg, lfs2_block_t block) {
int lfs2_emubd_sync(const struct lfs2_config *cfg) { int lfs2_emubd_sync(const struct lfs2_config *cfg) {
LFS2_EMUBD_TRACE("lfs2_emubd_sync(%p)", (void*)cfg); LFS2_EMUBD_TRACE("lfs2_emubd_sync(%p)", (void*)cfg);
lfs2_emubd_t *bd = cfg->context;
// do nothing // emulate out-of-order writes? reset first write, writes
(void)cfg; // cannot be out-of-order across sync
if (bd->cfg->powerloss_behavior == LFS2_EMUBD_POWERLOSS_OOO) {
lfs2_emubd_decblock(bd->ooo_data);
bd->ooo_block = -1;
bd->ooo_data = NULL;
}
LFS2_EMUBD_TRACE("lfs2_emubd_sync -> %d", 0); LFS2_EMUBD_TRACE("lfs2_emubd_sync -> %d", 0);
return 0; return 0;
} }
/// Additional extended API for driving test features /// /// Additional extended API for driving test features ///
static int lfs2_emubd_crc_(const struct lfs2_config *cfg, static int lfs2_emubd_crc_(const struct lfs2_config *cfg,
@@ -633,6 +725,8 @@ int lfs2_emubd_copy(const struct lfs2_config *cfg, lfs2_emubd_t *copy) {
copy->proged = bd->proged; copy->proged = bd->proged;
copy->erased = bd->erased; copy->erased = bd->erased;
copy->power_cycles = bd->power_cycles; copy->power_cycles = bd->power_cycles;
copy->ooo_block = bd->ooo_block;
copy->ooo_data = lfs2_emubd_incblock(bd->ooo_data);
copy->disk = bd->disk; copy->disk = bd->disk;
if (copy->disk) { if (copy->disk) {
copy->disk->rc += 1; copy->disk->rc += 1;
+9 -6
View File
@@ -36,17 +36,18 @@ extern "C"
// Not that read-noop is not allowed. Read _must_ return a consistent (but // Not that read-noop is not allowed. Read _must_ return a consistent (but
// may be arbitrary) value on every read. // may be arbitrary) value on every read.
typedef enum lfs2_emubd_badblock_behavior { typedef enum lfs2_emubd_badblock_behavior {
LFS2_EMUBD_BADBLOCK_PROGERROR, LFS2_EMUBD_BADBLOCK_PROGERROR = 0, // Error on prog
LFS2_EMUBD_BADBLOCK_ERASEERROR, LFS2_EMUBD_BADBLOCK_ERASEERROR = 1, // Error on erase
LFS2_EMUBD_BADBLOCK_READERROR, LFS2_EMUBD_BADBLOCK_READERROR = 2, // Error on read
LFS2_EMUBD_BADBLOCK_PROGNOOP, LFS2_EMUBD_BADBLOCK_PROGNOOP = 3, // Prog does nothing silently
LFS2_EMUBD_BADBLOCK_ERASENOOP, LFS2_EMUBD_BADBLOCK_ERASENOOP = 4, // Erase does nothing silently
} lfs2_emubd_badblock_behavior_t; } lfs2_emubd_badblock_behavior_t;
// Mode determining how power-loss behaves during testing. For now this // Mode determining how power-loss behaves during testing. For now this
// only supports a noop behavior, leaving the data on-disk untouched. // only supports a noop behavior, leaving the data on-disk untouched.
typedef enum lfs2_emubd_powerloss_behavior { typedef enum lfs2_emubd_powerloss_behavior {
LFS2_EMUBD_POWERLOSS_NOOP, LFS2_EMUBD_POWERLOSS_NOOP = 0, // Progs are atomic
LFS2_EMUBD_POWERLOSS_OOO = 1, // Blocks are written out-of-order
} lfs2_emubd_powerloss_behavior_t; } lfs2_emubd_powerloss_behavior_t;
// Type for measuring read/program/erase operations // Type for measuring read/program/erase operations
@@ -152,6 +153,8 @@ typedef struct lfs2_emubd {
lfs2_emubd_io_t proged; lfs2_emubd_io_t proged;
lfs2_emubd_io_t erased; lfs2_emubd_io_t erased;
lfs2_emubd_powercycles_t power_cycles; lfs2_emubd_powercycles_t power_cycles;
lfs2_ssize_t ooo_block;
lfs2_emubd_block_t *ooo_data;
lfs2_emubd_disk_t *disk; lfs2_emubd_disk_t *disk;
const struct lfs2_emubd_config *cfg; const struct lfs2_emubd_config *cfg;
+16 -4
View File
@@ -710,11 +710,14 @@ static lfs2_stag_t lfs2_dir_getslice(lfs2_t *lfs2, const lfs2_mdir_t *dir,
lfs2_tag_t ntag = dir->etag; lfs2_tag_t ntag = dir->etag;
lfs2_stag_t gdiff = 0; lfs2_stag_t gdiff = 0;
// synthetic moves
if (lfs2_gstate_hasmovehere(&lfs2->gdisk, dir->pair) && if (lfs2_gstate_hasmovehere(&lfs2->gdisk, dir->pair) &&
lfs2_tag_id(gmask) != 0 && lfs2_tag_id(gmask) != 0) {
lfs2_tag_id(lfs2->gdisk.tag) <= lfs2_tag_id(gtag)) { if (lfs2_tag_id(lfs2->gdisk.tag) == lfs2_tag_id(gtag)) {
// synthetic moves return LFS2_ERR_NOENT;
gdiff -= LFS2_MKTAG(0, 1, 0); } else if (lfs2_tag_id(lfs2->gdisk.tag) < lfs2_tag_id(gtag)) {
gdiff -= LFS2_MKTAG(0, 1, 0);
}
} }
// iterate over dir block backwards (for faster lookups) // iterate over dir block backwards (for faster lookups)
@@ -3401,6 +3404,15 @@ static int lfs2_file_sync_(lfs2_t *lfs2, lfs2_file_t *file) {
if ((file->flags & LFS2_F_DIRTY) && if ((file->flags & LFS2_F_DIRTY) &&
!lfs2_pair_isnull(file->m.pair)) { !lfs2_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 & LFS2_F_INLINE)) {
err = lfs2_bd_sync(lfs2, &lfs2->pcache, &lfs2->rcache, false);
if (err) {
return err;
}
}
// update dir entry // update dir entry
uint16_t type; uint16_t type;
const void *buffer; const void *buffer;
+8
View File
@@ -181,6 +181,10 @@ code = '''
defines.N = [5, 11] defines.N = [5, 11]
if = 'BLOCK_COUNT >= 4*N' if = 'BLOCK_COUNT >= 4*N'
reentrant = true reentrant = true
defines.POWERLOSS_BEHAVIOR = [
'LFS2_EMUBD_POWERLOSS_NOOP',
'LFS2_EMUBD_POWERLOSS_OOO',
]
code = ''' code = '''
lfs2_t lfs2; lfs2_t lfs2;
int err = lfs2_mount(&lfs2, cfg); int err = lfs2_mount(&lfs2, cfg);
@@ -439,6 +443,10 @@ code = '''
defines.N = [5, 25] defines.N = [5, 25]
if = 'N < BLOCK_COUNT/2' if = 'N < BLOCK_COUNT/2'
reentrant = true reentrant = true
defines.POWERLOSS_BEHAVIOR = [
'LFS2_EMUBD_POWERLOSS_NOOP',
'LFS2_EMUBD_POWERLOSS_OOO',
]
code = ''' code = '''
lfs2_t lfs2; lfs2_t lfs2;
int err = lfs2_mount(&lfs2, cfg); int err = lfs2_mount(&lfs2, cfg);
+8
View File
@@ -310,6 +310,10 @@ defines.SIZE = [32, 0, 7, 2049]
defines.CHUNKSIZE = [31, 16, 65] defines.CHUNKSIZE = [31, 16, 65]
defines.INLINE_MAX = [0, -1, 8] defines.INLINE_MAX = [0, -1, 8]
reentrant = true reentrant = true
defines.POWERLOSS_BEHAVIOR = [
'LFS2_EMUBD_POWERLOSS_NOOP',
'LFS2_EMUBD_POWERLOSS_OOO',
]
code = ''' code = '''
lfs2_t lfs2; lfs2_t lfs2;
int err = lfs2_mount(&lfs2, cfg); int err = lfs2_mount(&lfs2, cfg);
@@ -500,6 +504,10 @@ code = '''
[cases.test_files_many_power_loss] [cases.test_files_many_power_loss]
defines.N = 300 defines.N = 300
reentrant = true reentrant = true
defines.POWERLOSS_BEHAVIOR = [
'LFS2_EMUBD_POWERLOSS_NOOP',
'LFS2_EMUBD_POWERLOSS_OOO',
]
code = ''' code = '''
lfs2_t lfs2; lfs2_t lfs2;
int err = lfs2_mount(&lfs2, cfg); int err = lfs2_mount(&lfs2, cfg);
+4
View File
@@ -195,6 +195,10 @@ code = '''
defines.SIZE = [10, 100] defines.SIZE = [10, 100]
defines.FILES = [4, 10, 26] defines.FILES = [4, 10, 26]
reentrant = true reentrant = true
defines.POWERLOSS_BEHAVIOR = [
'LFS2_EMUBD_POWERLOSS_NOOP',
'LFS2_EMUBD_POWERLOSS_OOO',
]
code = ''' code = '''
lfs2_t lfs2; lfs2_t lfs2;
lfs2_file_t files[FILES]; lfs2_file_t files[FILES];
+8
View File
@@ -357,6 +357,10 @@ code = '''
[cases.test_move_reentrant_file] [cases.test_move_reentrant_file]
reentrant = true reentrant = true
defines.POWERLOSS_BEHAVIOR = [
'LFS2_EMUBD_POWERLOSS_NOOP',
'LFS2_EMUBD_POWERLOSS_OOO',
]
code = ''' code = '''
lfs2_t lfs2; lfs2_t lfs2;
int err = lfs2_mount(&lfs2, cfg); int err = lfs2_mount(&lfs2, cfg);
@@ -839,6 +843,10 @@ code = '''
[cases.test_reentrant_dir] [cases.test_reentrant_dir]
reentrant = true reentrant = true
defines.POWERLOSS_BEHAVIOR = [
'LFS2_EMUBD_POWERLOSS_NOOP',
'LFS2_EMUBD_POWERLOSS_OOO',
]
code = ''' code = '''
lfs2_t lfs2; lfs2_t lfs2;
int err = lfs2_mount(&lfs2, cfg); int err = lfs2_mount(&lfs2, cfg);
+4
View File
@@ -329,6 +329,10 @@ code = '''
# must be power-of-2 for quadratic probing to be exhaustive # must be power-of-2 for quadratic probing to be exhaustive
defines.COUNT = [4, 64, 128] defines.COUNT = [4, 64, 128]
reentrant = true reentrant = true
defines.POWERLOSS_BEHAVIOR = [
'LFS2_EMUBD_POWERLOSS_NOOP',
'LFS2_EMUBD_POWERLOSS_OOO',
]
code = ''' code = '''
lfs2_t lfs2; lfs2_t lfs2;
int err = lfs2_mount(&lfs2, cfg); int err = lfs2_mount(&lfs2, cfg);
+8
View File
@@ -32,6 +32,10 @@ code = '''
# reentrant format # reentrant format
[cases.test_superblocks_reentrant_format] [cases.test_superblocks_reentrant_format]
reentrant = true reentrant = true
defines.POWERLOSS_BEHAVIOR = [
'LFS2_EMUBD_POWERLOSS_NOOP',
'LFS2_EMUBD_POWERLOSS_OOO',
]
code = ''' code = '''
lfs2_t lfs2; lfs2_t lfs2;
int err = lfs2_mount(&lfs2, cfg); int err = lfs2_mount(&lfs2, cfg);
@@ -174,6 +178,10 @@ code = '''
defines.BLOCK_CYCLES = [2, 1] defines.BLOCK_CYCLES = [2, 1]
defines.N = 24 defines.N = 24
reentrant = true reentrant = true
defines.POWERLOSS_BEHAVIOR = [
'LFS2_EMUBD_POWERLOSS_NOOP',
'LFS2_EMUBD_POWERLOSS_OOO',
]
code = ''' code = '''
lfs2_t lfs2; lfs2_t lfs2;
int err = lfs2_mount(&lfs2, cfg); int err = lfs2_mount(&lfs2, cfg);
+4
View File
@@ -231,6 +231,10 @@ defines.SMALLSIZE = [4, 512]
defines.MEDIUMSIZE = [0, 3, 4, 5, 31, 32, 33, 511, 512, 513, 1023, 1024, 1025] defines.MEDIUMSIZE = [0, 3, 4, 5, 31, 32, 33, 511, 512, 513, 1023, 1024, 1025]
defines.LARGESIZE = 2048 defines.LARGESIZE = 2048
reentrant = true reentrant = true
defines.POWERLOSS_BEHAVIOR = [
'LFS2_EMUBD_POWERLOSS_NOOP',
'LFS2_EMUBD_POWERLOSS_OOO',
]
code = ''' code = '''
lfs2_t lfs2; lfs2_t lfs2;
int err = lfs2_mount(&lfs2, cfg); int err = lfs2_mount(&lfs2, cfg);