forked from Imagelibrary/littlefs
Compare commits
41 Commits
gc-compact
...
v2.9.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68d28b5114 | ||
|
|
1bc14933b7 | ||
|
|
01b6a47ea8 | ||
|
|
749a45650f | ||
|
|
4dd30c1b8f | ||
|
|
5c0d332ecd | ||
|
|
cf68333a55 | ||
|
|
7873d811a0 | ||
|
|
fc2aa3350c | ||
|
|
6352185949 | ||
|
|
f2a6f45eef | ||
|
|
2752d8c486 | ||
|
|
ddbfcaa722 | ||
|
|
f53a0cc961 | ||
|
|
42910bc8e5 | ||
|
|
a3e1d12ce1 | ||
|
|
a70870c628 | ||
|
|
ceb17a0f4a | ||
|
|
a8a0905777 | ||
|
|
13d78616fe | ||
|
|
8b8fd14187 | ||
|
|
09972a1710 | ||
|
|
ed7bd05435 | ||
|
|
1195d606ae | ||
|
|
1711bdef76 | ||
|
|
f522ed907a | ||
|
|
4f32738cd6 | ||
|
|
6691718b18 | ||
|
|
1fefcbbcba | ||
|
|
897b571318 | ||
|
|
3513ff1afc | ||
|
|
8a22bd6e67 | ||
|
|
9b82db72d8 | ||
|
|
99b84ee3db | ||
|
|
e91a29d2b5 | ||
|
|
b9b95ab4bc | ||
|
|
9a620c730c | ||
|
|
a0c6c54345 | ||
|
|
10bcff1af8 | ||
|
|
c531a5e88f | ||
|
|
8f9427dd53 |
2
.github/workflows/post-release.yml
vendored
2
.github/workflows/post-release.yml
vendored
@@ -10,7 +10,7 @@ defaults:
|
||||
|
||||
jobs:
|
||||
post-release:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# trigger post-release in dependency repo, this indirection allows the
|
||||
# dependency repo to be updated often without affecting this repo. At
|
||||
|
||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -11,7 +11,7 @@ defaults:
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# need to manually check for a couple things
|
||||
# - tests passed?
|
||||
@@ -112,7 +112,7 @@ jobs:
|
||||
table[$i,$j]=$c_camel
|
||||
((j+=1))
|
||||
|
||||
for s in code stack struct
|
||||
for s in code stack structs
|
||||
do
|
||||
f=sizes/thumb${c:+-$c}.$s.csv
|
||||
[ -e $f ] && table[$i,$j]=$( \
|
||||
|
||||
4
.github/workflows/status.yml
vendored
4
.github/workflows/status.yml
vendored
@@ -11,7 +11,7 @@ defaults:
|
||||
jobs:
|
||||
# forward custom statuses
|
||||
status:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dawidd6/action-download-artifact@v2
|
||||
continue-on-error: true
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
|
||||
# forward custom pr-comments
|
||||
comment:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# only run on success (we don't want garbage comments!)
|
||||
if: ${{github.event.workflow_run.conclusion == 'success'}}
|
||||
|
||||
24
.github/workflows/test.yml
vendored
24
.github/workflows/test.yml
vendored
@@ -14,7 +14,7 @@ env:
|
||||
jobs:
|
||||
# run tests
|
||||
test:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -329,7 +329,7 @@ jobs:
|
||||
#
|
||||
# this grows exponentially, so it doesn't turn out to be that many
|
||||
test-pls:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -359,7 +359,7 @@ jobs:
|
||||
|
||||
# run with LFS_NO_INTRINSICS to make sure that works
|
||||
test-no-intrinsics:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install
|
||||
@@ -376,7 +376,7 @@ jobs:
|
||||
|
||||
# run LFS_MULTIVERSION tests
|
||||
test-multiversion:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install
|
||||
@@ -393,7 +393,7 @@ jobs:
|
||||
|
||||
# run tests on the older version lfs2.0
|
||||
test-lfs2_0:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install
|
||||
@@ -412,7 +412,7 @@ jobs:
|
||||
|
||||
# run under Valgrind to check for memory errors
|
||||
test-valgrind:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install
|
||||
@@ -434,7 +434,7 @@ jobs:
|
||||
# test that compilation is warning free under clang
|
||||
# run with Clang, mostly to check for Clang-specific warnings
|
||||
test-clang:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install
|
||||
@@ -457,7 +457,7 @@ jobs:
|
||||
#
|
||||
# note there's no real benefit to running these on multiple archs
|
||||
bench:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install
|
||||
@@ -533,7 +533,7 @@ jobs:
|
||||
|
||||
# run compatibility tests using the current master as the previous version
|
||||
test-compat:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
if: ${{github.event_name == 'pull_request'}}
|
||||
@@ -569,7 +569,7 @@ jobs:
|
||||
|
||||
# self-host with littlefs-fuse for a fuzz-like test
|
||||
fuse:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{!endsWith(github.ref, '-prefix')}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -619,7 +619,7 @@ jobs:
|
||||
|
||||
# test migration using littlefs-fuse
|
||||
migrate:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{!endsWith(github.ref, '-prefix')}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -691,7 +691,7 @@ jobs:
|
||||
|
||||
# status related tasks that run after tests
|
||||
status:
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test, bench]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
@@ -59,7 +59,7 @@ This leaves us with three major requirements for an embedded filesystem.
|
||||
RAM to temporarily store filesystem metadata.
|
||||
|
||||
For ROM, this means we need to keep our design simple and reuse code paths
|
||||
were possible. For RAM we have a stronger requirement, all RAM usage is
|
||||
where possible. For RAM we have a stronger requirement, all RAM usage is
|
||||
bounded. This means RAM usage does not grow as the filesystem changes in
|
||||
size or number of files. This creates a unique challenge as even presumably
|
||||
simple operations, such as traversing the filesystem, become surprisingly
|
||||
@@ -626,7 +626,7 @@ log₂_n_ pointers that skip to different preceding elements of the
|
||||
skip-list.
|
||||
|
||||
The name comes from heavy use of the [CTZ instruction][wikipedia-ctz], which
|
||||
lets us calculate the power-of-two factors efficiently. For a give block _n_,
|
||||
lets us calculate the power-of-two factors efficiently. For a given block _n_,
|
||||
that block contains ctz(_n_)+1 pointers.
|
||||
|
||||
```
|
||||
|
||||
@@ -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
|
||||
|
||||
114
bd/lfs_emubd.c
114
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,17 +526,24 @@ 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_rawcrc(const struct lfs_config *cfg,
|
||||
static int lfs_emubd_crc_(const struct lfs_config *cfg,
|
||||
lfs_block_t block, uint32_t *crc) {
|
||||
lfs_emubd_t *bd = cfg->context;
|
||||
|
||||
@@ -480,7 +572,7 @@ int lfs_emubd_crc(const struct lfs_config *cfg,
|
||||
lfs_block_t block, uint32_t *crc) {
|
||||
LFS_EMUBD_TRACE("lfs_emubd_crc(%p, %"PRIu32", %p)",
|
||||
(void*)cfg, block, crc);
|
||||
int err = lfs_emubd_rawcrc(cfg, block, crc);
|
||||
int err = lfs_emubd_crc_(cfg, block, crc);
|
||||
LFS_EMUBD_TRACE("lfs_emubd_crc -> %d", err);
|
||||
return err;
|
||||
}
|
||||
@@ -491,7 +583,7 @@ int lfs_emubd_bdcrc(const struct lfs_config *cfg, uint32_t *crc) {
|
||||
uint32_t crc_ = 0xffffffff;
|
||||
for (lfs_block_t i = 0; i < cfg->block_count; i++) {
|
||||
uint32_t i_crc;
|
||||
int err = lfs_emubd_rawcrc(cfg, i, &i_crc);
|
||||
int err = lfs_emubd_crc_(cfg, i, &i_crc);
|
||||
if (err) {
|
||||
LFS_EMUBD_TRACE("lfs_emubd_bdcrc -> %d", err);
|
||||
return err;
|
||||
@@ -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;
|
||||
|
||||
268
lfs.c
268
lfs.c
@@ -550,9 +550,9 @@ static int lfs_dir_compact(lfs_t *lfs,
|
||||
lfs_mdir_t *source, uint16_t begin, uint16_t end);
|
||||
static lfs_ssize_t lfs_file_flushedwrite(lfs_t *lfs, lfs_file_t *file,
|
||||
const void *buffer, lfs_size_t size);
|
||||
static lfs_ssize_t lfs_file_rawwrite(lfs_t *lfs, lfs_file_t *file,
|
||||
static lfs_ssize_t lfs_file_write_(lfs_t *lfs, lfs_file_t *file,
|
||||
const void *buffer, lfs_size_t size);
|
||||
static int lfs_file_rawsync(lfs_t *lfs, lfs_file_t *file);
|
||||
static int lfs_file_sync_(lfs_t *lfs, lfs_file_t *file);
|
||||
static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file);
|
||||
static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file);
|
||||
|
||||
@@ -574,22 +574,22 @@ static int lfs1_traverse(lfs_t *lfs,
|
||||
int (*cb)(void*, lfs_block_t), void *data);
|
||||
#endif
|
||||
|
||||
static int lfs_dir_rawrewind(lfs_t *lfs, lfs_dir_t *dir);
|
||||
static int lfs_dir_rewind_(lfs_t *lfs, lfs_dir_t *dir);
|
||||
|
||||
static lfs_ssize_t lfs_file_flushedread(lfs_t *lfs, lfs_file_t *file,
|
||||
void *buffer, lfs_size_t size);
|
||||
static lfs_ssize_t lfs_file_rawread(lfs_t *lfs, lfs_file_t *file,
|
||||
static lfs_ssize_t lfs_file_read_(lfs_t *lfs, lfs_file_t *file,
|
||||
void *buffer, lfs_size_t size);
|
||||
static int lfs_file_rawclose(lfs_t *lfs, lfs_file_t *file);
|
||||
static lfs_soff_t lfs_file_rawsize(lfs_t *lfs, lfs_file_t *file);
|
||||
static int lfs_file_close_(lfs_t *lfs, lfs_file_t *file);
|
||||
static lfs_soff_t lfs_file_size_(lfs_t *lfs, lfs_file_t *file);
|
||||
|
||||
static lfs_ssize_t lfs_fs_rawsize(lfs_t *lfs);
|
||||
static int lfs_fs_rawtraverse(lfs_t *lfs,
|
||||
static lfs_ssize_t lfs_fs_size_(lfs_t *lfs);
|
||||
static int lfs_fs_traverse_(lfs_t *lfs,
|
||||
int (*cb)(void *data, lfs_block_t block), void *data,
|
||||
bool includeorphans);
|
||||
|
||||
static int lfs_deinit(lfs_t *lfs);
|
||||
static int lfs_rawunmount(lfs_t *lfs);
|
||||
static int lfs_unmount_(lfs_t *lfs);
|
||||
|
||||
|
||||
/// Block allocator ///
|
||||
@@ -639,7 +639,7 @@ static int lfs_alloc_scan(lfs_t *lfs) {
|
||||
|
||||
// find mask of free blocks from tree
|
||||
memset(lfs->lookahead.buffer, 0, lfs->cfg->lookahead_size);
|
||||
int err = lfs_fs_rawtraverse(lfs, lfs_alloc_lookahead, lfs, true);
|
||||
int err = lfs_fs_traverse_(lfs, lfs_alloc_lookahead, lfs, true);
|
||||
if (err) {
|
||||
lfs_alloc_drop(lfs);
|
||||
return err;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -710,11 +710,14 @@ static lfs_stag_t lfs_dir_getslice(lfs_t *lfs, const lfs_mdir_t *dir,
|
||||
lfs_tag_t ntag = dir->etag;
|
||||
lfs_stag_t gdiff = 0;
|
||||
|
||||
// synthetic moves
|
||||
if (lfs_gstate_hasmovehere(&lfs->gdisk, dir->pair) &&
|
||||
lfs_tag_id(gmask) != 0 &&
|
||||
lfs_tag_id(lfs->gdisk.tag) <= lfs_tag_id(gtag)) {
|
||||
// synthetic moves
|
||||
gdiff -= LFS_MKTAG(0, 1, 0);
|
||||
lfs_tag_id(gmask) != 0) {
|
||||
if (lfs_tag_id(lfs->gdisk.tag) == lfs_tag_id(gtag)) {
|
||||
return LFS_ERR_NOENT;
|
||||
} else if (lfs_tag_id(lfs->gdisk.tag) < lfs_tag_id(gtag)) {
|
||||
gdiff -= LFS_MKTAG(0, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// iterate over dir block backwards (for faster lookups)
|
||||
@@ -2166,14 +2169,16 @@ static int lfs_dir_splittingcompact(lfs_t *lfs, lfs_mdir_t *dir,
|
||||
&& lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0) {
|
||||
// oh no! we're writing too much to the superblock,
|
||||
// should we expand?
|
||||
lfs_ssize_t size = lfs_fs_rawsize(lfs);
|
||||
lfs_ssize_t size = lfs_fs_size_(lfs);
|
||||
if (size < 0) {
|
||||
return size;
|
||||
}
|
||||
|
||||
// do we have extra space? littlefs can't reclaim this space
|
||||
// by itself, so expand cautiously
|
||||
if ((lfs_size_t)size < lfs->block_count/2) {
|
||||
// littlefs cannot reclaim expanded superblocks, so expand cautiously
|
||||
//
|
||||
// if our filesystem is more than ~88% full, don't expand, this is
|
||||
// somewhat arbitrary
|
||||
if (lfs->block_count - size > lfs->block_count/8) {
|
||||
LFS_DEBUG("Expanding superblock at rev %"PRIu32, dir->rev);
|
||||
int err = lfs_dir_split(lfs, dir, attrs, attrcount,
|
||||
source, begin, end);
|
||||
@@ -2584,7 +2589,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
|
||||
|
||||
/// Top level directory operations ///
|
||||
#ifndef LFS_READONLY
|
||||
static int lfs_rawmkdir(lfs_t *lfs, const char *path) {
|
||||
static int lfs_mkdir_(lfs_t *lfs, const char *path) {
|
||||
// deorphan if we haven't yet, needed at most once after poweron
|
||||
int err = lfs_fs_forceconsistency(lfs);
|
||||
if (err) {
|
||||
@@ -2680,7 +2685,7 @@ static int lfs_rawmkdir(lfs_t *lfs, const char *path) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lfs_dir_rawopen(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
|
||||
static int lfs_dir_open_(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
|
||||
lfs_stag_t tag = lfs_dir_find(lfs, &dir->m, &path, NULL);
|
||||
if (tag < 0) {
|
||||
return tag;
|
||||
@@ -2724,14 +2729,14 @@ static int lfs_dir_rawopen(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lfs_dir_rawclose(lfs_t *lfs, lfs_dir_t *dir) {
|
||||
static int lfs_dir_close_(lfs_t *lfs, lfs_dir_t *dir) {
|
||||
// remove from list of mdirs
|
||||
lfs_mlist_remove(lfs, (struct lfs_mlist *)dir);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lfs_dir_rawread(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
|
||||
static int lfs_dir_read_(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
// special offset for '.' and '..'
|
||||
@@ -2776,9 +2781,9 @@ static int lfs_dir_rawread(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int lfs_dir_rawseek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
|
||||
static int lfs_dir_seek_(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
|
||||
// simply walk from head dir
|
||||
int err = lfs_dir_rawrewind(lfs, dir);
|
||||
int err = lfs_dir_rewind_(lfs, dir);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -2813,12 +2818,12 @@ static int lfs_dir_rawseek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static lfs_soff_t lfs_dir_rawtell(lfs_t *lfs, lfs_dir_t *dir) {
|
||||
static lfs_soff_t lfs_dir_tell_(lfs_t *lfs, lfs_dir_t *dir) {
|
||||
(void)lfs;
|
||||
return dir->pos;
|
||||
}
|
||||
|
||||
static int lfs_dir_rawrewind(lfs_t *lfs, lfs_dir_t *dir) {
|
||||
static int lfs_dir_rewind_(lfs_t *lfs, lfs_dir_t *dir) {
|
||||
// reload the head dir
|
||||
int err = lfs_dir_fetch(lfs, &dir->m, dir->head);
|
||||
if (err) {
|
||||
@@ -3024,7 +3029,7 @@ static int lfs_ctz_traverse(lfs_t *lfs,
|
||||
|
||||
|
||||
/// Top level file operations ///
|
||||
static int lfs_file_rawopencfg(lfs_t *lfs, lfs_file_t *file,
|
||||
static int lfs_file_opencfg_(lfs_t *lfs, lfs_file_t *file,
|
||||
const char *path, int flags,
|
||||
const struct lfs_file_config *cfg) {
|
||||
#ifndef LFS_READONLY
|
||||
@@ -3186,22 +3191,22 @@ cleanup:
|
||||
#ifndef LFS_READONLY
|
||||
file->flags |= LFS_F_ERRED;
|
||||
#endif
|
||||
lfs_file_rawclose(lfs, file);
|
||||
lfs_file_close_(lfs, file);
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifndef LFS_NO_MALLOC
|
||||
static int lfs_file_rawopen(lfs_t *lfs, lfs_file_t *file,
|
||||
static int lfs_file_open_(lfs_t *lfs, lfs_file_t *file,
|
||||
const char *path, int flags) {
|
||||
static const struct lfs_file_config defaults = {0};
|
||||
int err = lfs_file_rawopencfg(lfs, file, path, flags, &defaults);
|
||||
int err = lfs_file_opencfg_(lfs, file, path, flags, &defaults);
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lfs_file_rawclose(lfs_t *lfs, lfs_file_t *file) {
|
||||
static int lfs_file_close_(lfs_t *lfs, lfs_file_t *file) {
|
||||
#ifndef LFS_READONLY
|
||||
int err = lfs_file_rawsync(lfs, file);
|
||||
int err = lfs_file_sync_(lfs, file);
|
||||
#else
|
||||
int err = 0;
|
||||
#endif
|
||||
@@ -3384,7 +3389,7 @@ relocate:
|
||||
}
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
static int lfs_file_rawsync(lfs_t *lfs, lfs_file_t *file) {
|
||||
static int lfs_file_sync_(lfs_t *lfs, lfs_file_t *file) {
|
||||
if (file->flags & LFS_F_ERRED) {
|
||||
// it's not safe to do anything if our file errored
|
||||
return 0;
|
||||
@@ -3399,6 +3404,15 @@ static int lfs_file_rawsync(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;
|
||||
@@ -3497,7 +3511,7 @@ static lfs_ssize_t lfs_file_flushedread(lfs_t *lfs, lfs_file_t *file,
|
||||
return size;
|
||||
}
|
||||
|
||||
static lfs_ssize_t lfs_file_rawread(lfs_t *lfs, lfs_file_t *file,
|
||||
static lfs_ssize_t lfs_file_read_(lfs_t *lfs, lfs_file_t *file,
|
||||
void *buffer, lfs_size_t size) {
|
||||
LFS_ASSERT((file->flags & LFS_O_RDONLY) == LFS_O_RDONLY);
|
||||
|
||||
@@ -3522,11 +3536,7 @@ static lfs_ssize_t lfs_file_flushedwrite(lfs_t *lfs, lfs_file_t *file,
|
||||
lfs_size_t nsize = size;
|
||||
|
||||
if ((file->flags & LFS_F_INLINE) &&
|
||||
lfs_max(file->pos+nsize, file->ctz.size) >
|
||||
lfs_min(0x3fe, lfs_min(
|
||||
lfs->cfg->cache_size,
|
||||
(lfs->cfg->metadata_max ?
|
||||
lfs->cfg->metadata_max : lfs->cfg->block_size) / 8))) {
|
||||
lfs_max(file->pos+nsize, file->ctz.size) > lfs->inline_max) {
|
||||
// inline file doesn't fit anymore
|
||||
int err = lfs_file_outline(lfs, file);
|
||||
if (err) {
|
||||
@@ -3604,7 +3614,7 @@ relocate:
|
||||
return size;
|
||||
}
|
||||
|
||||
static lfs_ssize_t lfs_file_rawwrite(lfs_t *lfs, lfs_file_t *file,
|
||||
static lfs_ssize_t lfs_file_write_(lfs_t *lfs, lfs_file_t *file,
|
||||
const void *buffer, lfs_size_t size) {
|
||||
LFS_ASSERT((file->flags & LFS_O_WRONLY) == LFS_O_WRONLY);
|
||||
|
||||
@@ -3648,7 +3658,7 @@ static lfs_ssize_t lfs_file_rawwrite(lfs_t *lfs, lfs_file_t *file,
|
||||
}
|
||||
#endif
|
||||
|
||||
static lfs_soff_t lfs_file_rawseek(lfs_t *lfs, lfs_file_t *file,
|
||||
static lfs_soff_t lfs_file_seek_(lfs_t *lfs, lfs_file_t *file,
|
||||
lfs_soff_t off, int whence) {
|
||||
// find new pos
|
||||
lfs_off_t npos = file->pos;
|
||||
@@ -3661,7 +3671,7 @@ static lfs_soff_t lfs_file_rawseek(lfs_t *lfs, lfs_file_t *file,
|
||||
npos = file->pos + off;
|
||||
}
|
||||
} else if (whence == LFS_SEEK_END) {
|
||||
lfs_soff_t res = lfs_file_rawsize(lfs, file) + off;
|
||||
lfs_soff_t res = lfs_file_size_(lfs, file) + off;
|
||||
if (res < 0) {
|
||||
return LFS_ERR_INVAL;
|
||||
} else {
|
||||
@@ -3712,7 +3722,7 @@ static lfs_soff_t lfs_file_rawseek(lfs_t *lfs, lfs_file_t *file,
|
||||
}
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
static int lfs_file_rawtruncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
|
||||
static int lfs_file_truncate_(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
|
||||
LFS_ASSERT((file->flags & LFS_O_WRONLY) == LFS_O_WRONLY);
|
||||
|
||||
if (size > LFS_FILE_MAX) {
|
||||
@@ -3720,15 +3730,12 @@ static int lfs_file_rawtruncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
|
||||
}
|
||||
|
||||
lfs_off_t pos = file->pos;
|
||||
lfs_off_t oldsize = lfs_file_rawsize(lfs, file);
|
||||
lfs_off_t oldsize = lfs_file_size_(lfs, file);
|
||||
if (size < oldsize) {
|
||||
// revert to inline file?
|
||||
if (size <= lfs_min(0x3fe, lfs_min(
|
||||
lfs->cfg->cache_size,
|
||||
(lfs->cfg->metadata_max ?
|
||||
lfs->cfg->metadata_max : lfs->cfg->block_size) / 8))) {
|
||||
if (size <= lfs->inline_max) {
|
||||
// flush+seek to head
|
||||
lfs_soff_t res = lfs_file_rawseek(lfs, file, 0, LFS_SEEK_SET);
|
||||
lfs_soff_t res = lfs_file_seek_(lfs, file, 0, LFS_SEEK_SET);
|
||||
if (res < 0) {
|
||||
return (int)res;
|
||||
}
|
||||
@@ -3773,14 +3780,14 @@ static int lfs_file_rawtruncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
|
||||
}
|
||||
} else if (size > oldsize) {
|
||||
// flush+seek if not already at end
|
||||
lfs_soff_t res = lfs_file_rawseek(lfs, file, 0, LFS_SEEK_END);
|
||||
lfs_soff_t res = lfs_file_seek_(lfs, file, 0, LFS_SEEK_END);
|
||||
if (res < 0) {
|
||||
return (int)res;
|
||||
}
|
||||
|
||||
// fill with zeros
|
||||
while (file->pos < size) {
|
||||
res = lfs_file_rawwrite(lfs, file, &(uint8_t){0}, 1);
|
||||
res = lfs_file_write_(lfs, file, &(uint8_t){0}, 1);
|
||||
if (res < 0) {
|
||||
return (int)res;
|
||||
}
|
||||
@@ -3788,7 +3795,7 @@ static int lfs_file_rawtruncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
|
||||
}
|
||||
|
||||
// restore pos
|
||||
lfs_soff_t res = lfs_file_rawseek(lfs, file, pos, LFS_SEEK_SET);
|
||||
lfs_soff_t res = lfs_file_seek_(lfs, file, pos, LFS_SEEK_SET);
|
||||
if (res < 0) {
|
||||
return (int)res;
|
||||
}
|
||||
@@ -3797,13 +3804,13 @@ static int lfs_file_rawtruncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static lfs_soff_t lfs_file_rawtell(lfs_t *lfs, lfs_file_t *file) {
|
||||
static lfs_soff_t lfs_file_tell_(lfs_t *lfs, lfs_file_t *file) {
|
||||
(void)lfs;
|
||||
return file->pos;
|
||||
}
|
||||
|
||||
static int lfs_file_rawrewind(lfs_t *lfs, lfs_file_t *file) {
|
||||
lfs_soff_t res = lfs_file_rawseek(lfs, file, 0, LFS_SEEK_SET);
|
||||
static int lfs_file_rewind_(lfs_t *lfs, lfs_file_t *file) {
|
||||
lfs_soff_t res = lfs_file_seek_(lfs, file, 0, LFS_SEEK_SET);
|
||||
if (res < 0) {
|
||||
return (int)res;
|
||||
}
|
||||
@@ -3811,7 +3818,7 @@ static int lfs_file_rawrewind(lfs_t *lfs, lfs_file_t *file) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static lfs_soff_t lfs_file_rawsize(lfs_t *lfs, lfs_file_t *file) {
|
||||
static lfs_soff_t lfs_file_size_(lfs_t *lfs, lfs_file_t *file) {
|
||||
(void)lfs;
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
@@ -3825,7 +3832,7 @@ static lfs_soff_t lfs_file_rawsize(lfs_t *lfs, lfs_file_t *file) {
|
||||
|
||||
|
||||
/// General fs operations ///
|
||||
static int lfs_rawstat(lfs_t *lfs, const char *path, struct lfs_info *info) {
|
||||
static int lfs_stat_(lfs_t *lfs, const char *path, struct lfs_info *info) {
|
||||
lfs_mdir_t cwd;
|
||||
lfs_stag_t tag = lfs_dir_find(lfs, &cwd, &path, NULL);
|
||||
if (tag < 0) {
|
||||
@@ -3836,7 +3843,7 @@ static int lfs_rawstat(lfs_t *lfs, const char *path, struct lfs_info *info) {
|
||||
}
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
static int lfs_rawremove(lfs_t *lfs, const char *path) {
|
||||
static int lfs_remove_(lfs_t *lfs, const char *path) {
|
||||
// deorphan if we haven't yet, needed at most once after poweron
|
||||
int err = lfs_fs_forceconsistency(lfs);
|
||||
if (err) {
|
||||
@@ -3915,7 +3922,7 @@ static int lfs_rawremove(lfs_t *lfs, const char *path) {
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
static int lfs_rawrename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
||||
static int lfs_rename_(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
||||
// deorphan if we haven't yet, needed at most once after poweron
|
||||
int err = lfs_fs_forceconsistency(lfs);
|
||||
if (err) {
|
||||
@@ -3958,7 +3965,9 @@ static int lfs_rawrename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
||||
newoldid += 1;
|
||||
}
|
||||
} else if (lfs_tag_type3(prevtag) != lfs_tag_type3(oldtag)) {
|
||||
return LFS_ERR_ISDIR;
|
||||
return (lfs_tag_type3(prevtag) == LFS_TYPE_DIR)
|
||||
? LFS_ERR_ISDIR
|
||||
: LFS_ERR_NOTDIR;
|
||||
} else if (samepair && newid == newoldid) {
|
||||
// we're renaming to ourselves??
|
||||
return 0;
|
||||
@@ -4050,7 +4059,7 @@ static int lfs_rawrename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static lfs_ssize_t lfs_rawgetattr(lfs_t *lfs, const char *path,
|
||||
static lfs_ssize_t lfs_getattr_(lfs_t *lfs, const char *path,
|
||||
uint8_t type, void *buffer, lfs_size_t size) {
|
||||
lfs_mdir_t cwd;
|
||||
lfs_stag_t tag = lfs_dir_find(lfs, &cwd, &path, NULL);
|
||||
@@ -4108,7 +4117,7 @@ static int lfs_commitattr(lfs_t *lfs, const char *path,
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
static int lfs_rawsetattr(lfs_t *lfs, const char *path,
|
||||
static int lfs_setattr_(lfs_t *lfs, const char *path,
|
||||
uint8_t type, const void *buffer, lfs_size_t size) {
|
||||
if (size > lfs->attr_max) {
|
||||
return LFS_ERR_NOSPC;
|
||||
@@ -4119,13 +4128,28 @@ static int lfs_rawsetattr(lfs_t *lfs, const char *path,
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
static int lfs_rawremoveattr(lfs_t *lfs, const char *path, uint8_t type) {
|
||||
static int lfs_removeattr_(lfs_t *lfs, const char *path, uint8_t type) {
|
||||
return lfs_commitattr(lfs, path, type, NULL, 0x3ff);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/// Filesystem operations ///
|
||||
|
||||
// compile time checks, see lfs.h for why these limits exist
|
||||
#if LFS_NAME_MAX > 1022
|
||||
#error "Invalid LFS_NAME_MAX, must be <= 1022"
|
||||
#endif
|
||||
|
||||
#if LFS_FILE_MAX > 2147483647
|
||||
#error "Invalid LFS_FILE_MAX, must be <= 2147483647"
|
||||
#endif
|
||||
|
||||
#if LFS_ATTR_MAX > 1022
|
||||
#error "Invalid LFS_ATTR_MAX, must be <= 1022"
|
||||
#endif
|
||||
|
||||
// common filesystem initialization
|
||||
static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
lfs->cfg = cfg;
|
||||
lfs->block_count = cfg->block_count; // May be 0
|
||||
@@ -4242,6 +4266,27 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
|
||||
LFS_ASSERT(lfs->cfg->metadata_max <= lfs->cfg->block_size);
|
||||
|
||||
LFS_ASSERT(lfs->cfg->inline_max == (lfs_size_t)-1
|
||||
|| lfs->cfg->inline_max <= lfs->cfg->cache_size);
|
||||
LFS_ASSERT(lfs->cfg->inline_max == (lfs_size_t)-1
|
||||
|| lfs->cfg->inline_max <= lfs->attr_max);
|
||||
LFS_ASSERT(lfs->cfg->inline_max == (lfs_size_t)-1
|
||||
|| lfs->cfg->inline_max <= ((lfs->cfg->metadata_max)
|
||||
? lfs->cfg->metadata_max
|
||||
: lfs->cfg->block_size)/8);
|
||||
lfs->inline_max = lfs->cfg->inline_max;
|
||||
if (lfs->inline_max == (lfs_size_t)-1) {
|
||||
lfs->inline_max = 0;
|
||||
} else if (lfs->inline_max == 0) {
|
||||
lfs->inline_max = lfs_min(
|
||||
lfs->cfg->cache_size,
|
||||
lfs_min(
|
||||
lfs->attr_max,
|
||||
((lfs->cfg->metadata_max)
|
||||
? lfs->cfg->metadata_max
|
||||
: lfs->cfg->block_size)/8));
|
||||
}
|
||||
|
||||
// setup default state
|
||||
lfs->root[0] = LFS_BLOCK_NULL;
|
||||
lfs->root[1] = LFS_BLOCK_NULL;
|
||||
@@ -4281,7 +4326,7 @@ static int lfs_deinit(lfs_t *lfs) {
|
||||
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
static int lfs_rawformat(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
static int lfs_format_(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
int err = 0;
|
||||
{
|
||||
err = lfs_init(lfs, cfg);
|
||||
@@ -4348,7 +4393,7 @@ cleanup:
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lfs_rawmount(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
static int lfs_mount_(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
int err = lfs_init(lfs, cfg);
|
||||
if (err) {
|
||||
return err;
|
||||
@@ -4465,6 +4510,9 @@ static int lfs_rawmount(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
}
|
||||
|
||||
lfs->attr_max = superblock.attr_max;
|
||||
|
||||
// we also need to update inline_max in case attr_max changed
|
||||
lfs->inline_max = lfs_min(lfs->inline_max, lfs->attr_max);
|
||||
}
|
||||
|
||||
// this is where we get the block_count from disk if block_count=0
|
||||
@@ -4511,17 +4559,17 @@ static int lfs_rawmount(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
return 0;
|
||||
|
||||
cleanup:
|
||||
lfs_rawunmount(lfs);
|
||||
lfs_unmount_(lfs);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int lfs_rawunmount(lfs_t *lfs) {
|
||||
static int lfs_unmount_(lfs_t *lfs) {
|
||||
return lfs_deinit(lfs);
|
||||
}
|
||||
|
||||
|
||||
/// Filesystem filesystem operations ///
|
||||
static int lfs_fs_rawstat(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {
|
||||
static int lfs_fs_stat_(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {
|
||||
// if the superblock is up-to-date, we must be on the most recent
|
||||
// minor version of littlefs
|
||||
if (!lfs_gstate_needssuperblock(&lfs->gstate)) {
|
||||
@@ -4561,7 +4609,7 @@ static int lfs_fs_rawstat(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lfs_fs_rawtraverse(lfs_t *lfs,
|
||||
int lfs_fs_traverse_(lfs_t *lfs,
|
||||
int (*cb)(void *data, lfs_block_t block), void *data,
|
||||
bool includeorphans) {
|
||||
// iterate over metadata pairs
|
||||
@@ -5026,7 +5074,7 @@ static int lfs_fs_forceconsistency(lfs_t *lfs) {
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
static int lfs_fs_rawmkconsistent(lfs_t *lfs) {
|
||||
static int lfs_fs_mkconsistent_(lfs_t *lfs) {
|
||||
// lfs_fs_forceconsistency does most of the work here
|
||||
int err = lfs_fs_forceconsistency(lfs);
|
||||
if (err) {
|
||||
@@ -5062,9 +5110,9 @@ static int lfs_fs_size_count(void *p, lfs_block_t block) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static lfs_ssize_t lfs_fs_rawsize(lfs_t *lfs) {
|
||||
static lfs_ssize_t lfs_fs_size_(lfs_t *lfs) {
|
||||
lfs_size_t size = 0;
|
||||
int err = lfs_fs_rawtraverse(lfs, lfs_fs_size_count, &size, false);
|
||||
int err = lfs_fs_traverse_(lfs, lfs_fs_size_count, &size, false);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
@@ -5074,7 +5122,7 @@ static lfs_ssize_t lfs_fs_rawsize(lfs_t *lfs) {
|
||||
|
||||
// explicit garbage collection
|
||||
#ifndef LFS_READONLY
|
||||
static int lfs_fs_rawgc(lfs_t *lfs) {
|
||||
static int lfs_fs_gc_(lfs_t *lfs) {
|
||||
// force consistency, even if we're not necessarily going to write,
|
||||
// because this function is supposed to take care of janitorial work
|
||||
// isn't it?
|
||||
@@ -5124,7 +5172,7 @@ static int lfs_fs_rawgc(lfs_t *lfs) {
|
||||
#endif
|
||||
|
||||
#ifndef LFS_READONLY
|
||||
static int lfs_fs_rawgrow(lfs_t *lfs, lfs_size_t block_count) {
|
||||
static int lfs_fs_grow_(lfs_t *lfs, lfs_size_t block_count) {
|
||||
// shrinking is not supported
|
||||
LFS_ASSERT(block_count >= lfs->block_count);
|
||||
|
||||
@@ -5583,7 +5631,7 @@ static int lfs1_unmount(lfs_t *lfs) {
|
||||
}
|
||||
|
||||
/// v1 migration ///
|
||||
static int lfs_rawmigrate(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
static int lfs_migrate_(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
struct lfs1 lfs1;
|
||||
|
||||
// Indeterminate filesystem size not allowed for migration.
|
||||
@@ -5850,7 +5898,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
|
||||
cfg->name_max, cfg->file_max, cfg->attr_max);
|
||||
|
||||
err = lfs_rawformat(lfs, cfg);
|
||||
err = lfs_format_(lfs, cfg);
|
||||
|
||||
LFS_TRACE("lfs_format -> %d", err);
|
||||
LFS_UNLOCK(cfg);
|
||||
@@ -5880,7 +5928,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
|
||||
cfg->name_max, cfg->file_max, cfg->attr_max);
|
||||
|
||||
err = lfs_rawmount(lfs, cfg);
|
||||
err = lfs_mount_(lfs, cfg);
|
||||
|
||||
LFS_TRACE("lfs_mount -> %d", err);
|
||||
LFS_UNLOCK(cfg);
|
||||
@@ -5894,7 +5942,7 @@ int lfs_unmount(lfs_t *lfs) {
|
||||
}
|
||||
LFS_TRACE("lfs_unmount(%p)", (void*)lfs);
|
||||
|
||||
err = lfs_rawunmount(lfs);
|
||||
err = lfs_unmount_(lfs);
|
||||
|
||||
LFS_TRACE("lfs_unmount -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -5909,7 +5957,7 @@ int lfs_remove(lfs_t *lfs, const char *path) {
|
||||
}
|
||||
LFS_TRACE("lfs_remove(%p, \"%s\")", (void*)lfs, path);
|
||||
|
||||
err = lfs_rawremove(lfs, path);
|
||||
err = lfs_remove_(lfs, path);
|
||||
|
||||
LFS_TRACE("lfs_remove -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -5925,7 +5973,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
||||
}
|
||||
LFS_TRACE("lfs_rename(%p, \"%s\", \"%s\")", (void*)lfs, oldpath, newpath);
|
||||
|
||||
err = lfs_rawrename(lfs, oldpath, newpath);
|
||||
err = lfs_rename_(lfs, oldpath, newpath);
|
||||
|
||||
LFS_TRACE("lfs_rename -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -5940,7 +5988,7 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
|
||||
}
|
||||
LFS_TRACE("lfs_stat(%p, \"%s\", %p)", (void*)lfs, path, (void*)info);
|
||||
|
||||
err = lfs_rawstat(lfs, path, info);
|
||||
err = lfs_stat_(lfs, path, info);
|
||||
|
||||
LFS_TRACE("lfs_stat -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -5956,7 +6004,7 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
|
||||
LFS_TRACE("lfs_getattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")",
|
||||
(void*)lfs, path, type, buffer, size);
|
||||
|
||||
lfs_ssize_t res = lfs_rawgetattr(lfs, path, type, buffer, size);
|
||||
lfs_ssize_t res = lfs_getattr_(lfs, path, type, buffer, size);
|
||||
|
||||
LFS_TRACE("lfs_getattr -> %"PRId32, res);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -5973,7 +6021,7 @@ int lfs_setattr(lfs_t *lfs, const char *path,
|
||||
LFS_TRACE("lfs_setattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")",
|
||||
(void*)lfs, path, type, buffer, size);
|
||||
|
||||
err = lfs_rawsetattr(lfs, path, type, buffer, size);
|
||||
err = lfs_setattr_(lfs, path, type, buffer, size);
|
||||
|
||||
LFS_TRACE("lfs_setattr -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -5989,7 +6037,7 @@ int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type) {
|
||||
}
|
||||
LFS_TRACE("lfs_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs, path, type);
|
||||
|
||||
err = lfs_rawremoveattr(lfs, path, type);
|
||||
err = lfs_removeattr_(lfs, path, type);
|
||||
|
||||
LFS_TRACE("lfs_removeattr -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6007,7 +6055,7 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, const char *path, int flags) {
|
||||
(void*)lfs, (void*)file, path, flags);
|
||||
LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
|
||||
|
||||
err = lfs_file_rawopen(lfs, file, path, flags);
|
||||
err = lfs_file_open_(lfs, file, path, flags);
|
||||
|
||||
LFS_TRACE("lfs_file_open -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6028,7 +6076,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
|
||||
(void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count);
|
||||
LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
|
||||
|
||||
err = lfs_file_rawopencfg(lfs, file, path, flags, cfg);
|
||||
err = lfs_file_opencfg_(lfs, file, path, flags, cfg);
|
||||
|
||||
LFS_TRACE("lfs_file_opencfg -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6043,7 +6091,7 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) {
|
||||
LFS_TRACE("lfs_file_close(%p, %p)", (void*)lfs, (void*)file);
|
||||
LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
|
||||
|
||||
err = lfs_file_rawclose(lfs, file);
|
||||
err = lfs_file_close_(lfs, file);
|
||||
|
||||
LFS_TRACE("lfs_file_close -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6059,7 +6107,7 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
|
||||
LFS_TRACE("lfs_file_sync(%p, %p)", (void*)lfs, (void*)file);
|
||||
LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
|
||||
|
||||
err = lfs_file_rawsync(lfs, file);
|
||||
err = lfs_file_sync_(lfs, file);
|
||||
|
||||
LFS_TRACE("lfs_file_sync -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6077,7 +6125,7 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
|
||||
(void*)lfs, (void*)file, buffer, size);
|
||||
LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
|
||||
|
||||
lfs_ssize_t res = lfs_file_rawread(lfs, file, buffer, size);
|
||||
lfs_ssize_t res = lfs_file_read_(lfs, file, buffer, size);
|
||||
|
||||
LFS_TRACE("lfs_file_read -> %"PRId32, res);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6095,7 +6143,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
|
||||
(void*)lfs, (void*)file, buffer, size);
|
||||
LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
|
||||
|
||||
lfs_ssize_t res = lfs_file_rawwrite(lfs, file, buffer, size);
|
||||
lfs_ssize_t res = lfs_file_write_(lfs, file, buffer, size);
|
||||
|
||||
LFS_TRACE("lfs_file_write -> %"PRId32, res);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6113,7 +6161,7 @@ lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
|
||||
(void*)lfs, (void*)file, off, whence);
|
||||
LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
|
||||
|
||||
lfs_soff_t res = lfs_file_rawseek(lfs, file, off, whence);
|
||||
lfs_soff_t res = lfs_file_seek_(lfs, file, off, whence);
|
||||
|
||||
LFS_TRACE("lfs_file_seek -> %"PRId32, res);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6130,7 +6178,7 @@ int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
|
||||
(void*)lfs, (void*)file, size);
|
||||
LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
|
||||
|
||||
err = lfs_file_rawtruncate(lfs, file, size);
|
||||
err = lfs_file_truncate_(lfs, file, size);
|
||||
|
||||
LFS_TRACE("lfs_file_truncate -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6146,7 +6194,7 @@ lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file) {
|
||||
LFS_TRACE("lfs_file_tell(%p, %p)", (void*)lfs, (void*)file);
|
||||
LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
|
||||
|
||||
lfs_soff_t res = lfs_file_rawtell(lfs, file);
|
||||
lfs_soff_t res = lfs_file_tell_(lfs, file);
|
||||
|
||||
LFS_TRACE("lfs_file_tell -> %"PRId32, res);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6160,7 +6208,7 @@ int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file) {
|
||||
}
|
||||
LFS_TRACE("lfs_file_rewind(%p, %p)", (void*)lfs, (void*)file);
|
||||
|
||||
err = lfs_file_rawrewind(lfs, file);
|
||||
err = lfs_file_rewind_(lfs, file);
|
||||
|
||||
LFS_TRACE("lfs_file_rewind -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6175,7 +6223,7 @@ lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file) {
|
||||
LFS_TRACE("lfs_file_size(%p, %p)", (void*)lfs, (void*)file);
|
||||
LFS_ASSERT(lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)file));
|
||||
|
||||
lfs_soff_t res = lfs_file_rawsize(lfs, file);
|
||||
lfs_soff_t res = lfs_file_size_(lfs, file);
|
||||
|
||||
LFS_TRACE("lfs_file_size -> %"PRId32, res);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6190,7 +6238,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
|
||||
}
|
||||
LFS_TRACE("lfs_mkdir(%p, \"%s\")", (void*)lfs, path);
|
||||
|
||||
err = lfs_rawmkdir(lfs, path);
|
||||
err = lfs_mkdir_(lfs, path);
|
||||
|
||||
LFS_TRACE("lfs_mkdir -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6206,7 +6254,7 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
|
||||
LFS_TRACE("lfs_dir_open(%p, %p, \"%s\")", (void*)lfs, (void*)dir, path);
|
||||
LFS_ASSERT(!lfs_mlist_isopen(lfs->mlist, (struct lfs_mlist*)dir));
|
||||
|
||||
err = lfs_dir_rawopen(lfs, dir, path);
|
||||
err = lfs_dir_open_(lfs, dir, path);
|
||||
|
||||
LFS_TRACE("lfs_dir_open -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6220,7 +6268,7 @@ int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) {
|
||||
}
|
||||
LFS_TRACE("lfs_dir_close(%p, %p)", (void*)lfs, (void*)dir);
|
||||
|
||||
err = lfs_dir_rawclose(lfs, dir);
|
||||
err = lfs_dir_close_(lfs, dir);
|
||||
|
||||
LFS_TRACE("lfs_dir_close -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6235,7 +6283,7 @@ int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
|
||||
LFS_TRACE("lfs_dir_read(%p, %p, %p)",
|
||||
(void*)lfs, (void*)dir, (void*)info);
|
||||
|
||||
err = lfs_dir_rawread(lfs, dir, info);
|
||||
err = lfs_dir_read_(lfs, dir, info);
|
||||
|
||||
LFS_TRACE("lfs_dir_read -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6250,7 +6298,7 @@ int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off) {
|
||||
LFS_TRACE("lfs_dir_seek(%p, %p, %"PRIu32")",
|
||||
(void*)lfs, (void*)dir, off);
|
||||
|
||||
err = lfs_dir_rawseek(lfs, dir, off);
|
||||
err = lfs_dir_seek_(lfs, dir, off);
|
||||
|
||||
LFS_TRACE("lfs_dir_seek -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6264,7 +6312,7 @@ lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir) {
|
||||
}
|
||||
LFS_TRACE("lfs_dir_tell(%p, %p)", (void*)lfs, (void*)dir);
|
||||
|
||||
lfs_soff_t res = lfs_dir_rawtell(lfs, dir);
|
||||
lfs_soff_t res = lfs_dir_tell_(lfs, dir);
|
||||
|
||||
LFS_TRACE("lfs_dir_tell -> %"PRId32, res);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6278,7 +6326,7 @@ int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir) {
|
||||
}
|
||||
LFS_TRACE("lfs_dir_rewind(%p, %p)", (void*)lfs, (void*)dir);
|
||||
|
||||
err = lfs_dir_rawrewind(lfs, dir);
|
||||
err = lfs_dir_rewind_(lfs, dir);
|
||||
|
||||
LFS_TRACE("lfs_dir_rewind -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6292,7 +6340,7 @@ int lfs_fs_stat(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {
|
||||
}
|
||||
LFS_TRACE("lfs_fs_stat(%p, %p)", (void*)lfs, (void*)fsinfo);
|
||||
|
||||
err = lfs_fs_rawstat(lfs, fsinfo);
|
||||
err = lfs_fs_stat_(lfs, fsinfo);
|
||||
|
||||
LFS_TRACE("lfs_fs_stat -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6306,7 +6354,7 @@ lfs_ssize_t lfs_fs_size(lfs_t *lfs) {
|
||||
}
|
||||
LFS_TRACE("lfs_fs_size(%p)", (void*)lfs);
|
||||
|
||||
lfs_ssize_t res = lfs_fs_rawsize(lfs);
|
||||
lfs_ssize_t res = lfs_fs_size_(lfs);
|
||||
|
||||
LFS_TRACE("lfs_fs_size -> %"PRId32, res);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6321,7 +6369,7 @@ int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void *, lfs_block_t), void *data) {
|
||||
LFS_TRACE("lfs_fs_traverse(%p, %p, %p)",
|
||||
(void*)lfs, (void*)(uintptr_t)cb, data);
|
||||
|
||||
err = lfs_fs_rawtraverse(lfs, cb, data, true);
|
||||
err = lfs_fs_traverse_(lfs, cb, data, true);
|
||||
|
||||
LFS_TRACE("lfs_fs_traverse -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6336,7 +6384,7 @@ int lfs_fs_mkconsistent(lfs_t *lfs) {
|
||||
}
|
||||
LFS_TRACE("lfs_fs_mkconsistent(%p)", (void*)lfs);
|
||||
|
||||
err = lfs_fs_rawmkconsistent(lfs);
|
||||
err = lfs_fs_mkconsistent_(lfs);
|
||||
|
||||
LFS_TRACE("lfs_fs_mkconsistent -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6352,7 +6400,7 @@ int lfs_fs_gc(lfs_t *lfs) {
|
||||
}
|
||||
LFS_TRACE("lfs_fs_gc(%p)", (void*)lfs);
|
||||
|
||||
err = lfs_fs_rawgc(lfs);
|
||||
err = lfs_fs_gc_(lfs);
|
||||
|
||||
LFS_TRACE("lfs_fs_gc -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6368,7 +6416,7 @@ int lfs_fs_grow(lfs_t *lfs, lfs_size_t block_count) {
|
||||
}
|
||||
LFS_TRACE("lfs_fs_grow(%p, %"PRIu32")", (void*)lfs, block_count);
|
||||
|
||||
err = lfs_fs_rawgrow(lfs, block_count);
|
||||
err = lfs_fs_grow_(lfs, block_count);
|
||||
|
||||
LFS_TRACE("lfs_fs_grow -> %d", err);
|
||||
LFS_UNLOCK(lfs->cfg);
|
||||
@@ -6399,7 +6447,7 @@ int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||
cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
|
||||
cfg->name_max, cfg->file_max, cfg->attr_max);
|
||||
|
||||
err = lfs_rawmigrate(lfs, cfg);
|
||||
err = lfs_migrate_(lfs, cfg);
|
||||
|
||||
LFS_TRACE("lfs_migrate -> %d", err);
|
||||
LFS_UNLOCK(cfg);
|
||||
|
||||
34
lfs.h
34
lfs.h
@@ -21,7 +21,7 @@ extern "C"
|
||||
// Software library version
|
||||
// Major (top-nibble), incremented on backwards incompatible changes
|
||||
// Minor (bottom-nibble), incremented on feature additions
|
||||
#define LFS_VERSION 0x00020008
|
||||
#define LFS_VERSION 0x00020009
|
||||
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
|
||||
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
|
||||
|
||||
@@ -52,16 +52,15 @@ typedef uint32_t lfs_block_t;
|
||||
#endif
|
||||
|
||||
// Maximum size of a file in bytes, may be redefined to limit to support other
|
||||
// drivers. Limited on disk to <= 4294967296. However, above 2147483647 the
|
||||
// functions lfs_file_seek, lfs_file_size, and lfs_file_tell will return
|
||||
// incorrect values due to using signed integers. Stored in superblock and
|
||||
// must be respected by other littlefs drivers.
|
||||
// drivers. Limited on disk to <= 2147483647. Stored in superblock and must be
|
||||
// respected by other littlefs drivers.
|
||||
#ifndef LFS_FILE_MAX
|
||||
#define LFS_FILE_MAX 2147483647
|
||||
#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
|
||||
@@ -205,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
|
||||
@@ -254,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
|
||||
@@ -274,6 +274,15 @@ struct lfs_config {
|
||||
// Defaults to block_size when zero.
|
||||
lfs_size_t metadata_max;
|
||||
|
||||
// Optional upper limit on inlined files in bytes. Inlined files live in
|
||||
// metadata and decrease storage requirements, but may be limited to
|
||||
// improve metadata-related performance. Must be <= cache_size, <=
|
||||
// attr_max, and <= block_size/8. Defaults to the largest possible
|
||||
// inline_max when zero.
|
||||
//
|
||||
// Set to -1 to disable inlined files.
|
||||
lfs_size_t inline_max;
|
||||
|
||||
#ifdef LFS_MULTIVERSION
|
||||
// On-disk version to use when writing in the form of 16-bit major version
|
||||
// + 16-bit minor version. This limiting metadata to what is supported by
|
||||
@@ -453,6 +462,7 @@ typedef struct lfs {
|
||||
lfs_size_t name_max;
|
||||
lfs_size_t file_max;
|
||||
lfs_size_t attr_max;
|
||||
lfs_size_t inline_max;
|
||||
|
||||
#ifdef LFS_MIGRATE
|
||||
struct lfs1 *lfs1;
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
#ifndef LFS_CONFIG
|
||||
|
||||
|
||||
// If user provides their own CRC impl we don't need this
|
||||
#ifndef LFS_CRC
|
||||
// Software CRC implementation with small lookup table
|
||||
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
|
||||
static const uint32_t rtable[16] = {
|
||||
@@ -29,6 +31,7 @@ uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
|
||||
|
||||
return crc;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
14
lfs_util.h
14
lfs_util.h
@@ -212,14 +212,22 @@ static inline uint32_t lfs_tobe32(uint32_t a) {
|
||||
}
|
||||
|
||||
// Calculate CRC-32 with polynomial = 0x04c11db7
|
||||
#ifdef LFS_CRC
|
||||
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
|
||||
return LFS_CRC(crc, buffer, size)
|
||||
}
|
||||
#else
|
||||
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);
|
||||
#endif
|
||||
|
||||
// Allocate memory, only used if buffers are not provided to littlefs
|
||||
//
|
||||
// littlefs current has no alignment requirements, as it only allocates
|
||||
// byte-level buffers.
|
||||
static inline void *lfs_malloc(size_t size) {
|
||||
#ifndef LFS_NO_MALLOC
|
||||
#if defined(LFS_MALLOC)
|
||||
return LFS_MALLOC(size);
|
||||
#elif !defined(LFS_NO_MALLOC)
|
||||
return malloc(size);
|
||||
#else
|
||||
(void)size;
|
||||
@@ -229,7 +237,9 @@ static inline void *lfs_malloc(size_t size) {
|
||||
|
||||
// Deallocate memory, only used if buffers are not provided to littlefs
|
||||
static inline void lfs_free(void *p) {
|
||||
#ifndef LFS_NO_MALLOC
|
||||
#if defined(LFS_FREE)
|
||||
LFS_FREE(p);
|
||||
#elif !defined(LFS_NO_MALLOC)
|
||||
free(p);
|
||||
#else
|
||||
(void)p;
|
||||
|
||||
@@ -1322,6 +1322,7 @@ void perm_run(
|
||||
.cache_size = CACHE_SIZE,
|
||||
.lookahead_size = LOOKAHEAD_SIZE,
|
||||
.compact_thresh = COMPACT_THRESH,
|
||||
.inline_max = INLINE_MAX,
|
||||
};
|
||||
|
||||
struct lfs_emubd_config bdcfg = {
|
||||
|
||||
@@ -96,11 +96,12 @@ intmax_t bench_define(size_t define);
|
||||
#define CACHE_SIZE_i 6
|
||||
#define LOOKAHEAD_SIZE_i 7
|
||||
#define COMPACT_THRESH_i 8
|
||||
#define BLOCK_CYCLES_i 9
|
||||
#define ERASE_VALUE_i 10
|
||||
#define ERASE_CYCLES_i 11
|
||||
#define BADBLOCK_BEHAVIOR_i 12
|
||||
#define POWERLOSS_BEHAVIOR_i 13
|
||||
#define INLINE_MAX_i 9
|
||||
#define BLOCK_CYCLES_i 10
|
||||
#define ERASE_VALUE_i 11
|
||||
#define ERASE_CYCLES_i 12
|
||||
#define BADBLOCK_BEHAVIOR_i 13
|
||||
#define POWERLOSS_BEHAVIOR_i 14
|
||||
|
||||
#define READ_SIZE bench_define(READ_SIZE_i)
|
||||
#define PROG_SIZE bench_define(PROG_SIZE_i)
|
||||
@@ -111,6 +112,7 @@ intmax_t bench_define(size_t define);
|
||||
#define CACHE_SIZE bench_define(CACHE_SIZE_i)
|
||||
#define LOOKAHEAD_SIZE bench_define(LOOKAHEAD_SIZE_i)
|
||||
#define COMPACT_THRESH bench_define(COMPACT_THRESH_i)
|
||||
#define INLINE_MAX bench_define(INLINE_MAX_i)
|
||||
#define BLOCK_CYCLES bench_define(BLOCK_CYCLES_i)
|
||||
#define ERASE_VALUE bench_define(ERASE_VALUE_i)
|
||||
#define ERASE_CYCLES bench_define(ERASE_CYCLES_i)
|
||||
@@ -127,6 +129,7 @@ intmax_t bench_define(size_t define);
|
||||
BENCH_DEF(CACHE_SIZE, lfs_max(64,lfs_max(READ_SIZE,PROG_SIZE))) \
|
||||
BENCH_DEF(LOOKAHEAD_SIZE, 16) \
|
||||
BENCH_DEF(COMPACT_THRESH, 0) \
|
||||
BENCH_DEF(INLINE_MAX, 0) \
|
||||
BENCH_DEF(BLOCK_CYCLES, -1) \
|
||||
BENCH_DEF(ERASE_VALUE, 0xff) \
|
||||
BENCH_DEF(ERASE_CYCLES, 0) \
|
||||
@@ -134,7 +137,7 @@ intmax_t bench_define(size_t define);
|
||||
BENCH_DEF(POWERLOSS_BEHAVIOR, LFS_EMUBD_POWERLOSS_NOOP)
|
||||
|
||||
#define BENCH_GEOMETRY_DEFINE_COUNT 4
|
||||
#define BENCH_IMPLICIT_DEFINE_COUNT 14
|
||||
#define BENCH_IMPLICIT_DEFINE_COUNT 15
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1347,6 +1347,7 @@ static void run_powerloss_none(
|
||||
.cache_size = CACHE_SIZE,
|
||||
.lookahead_size = LOOKAHEAD_SIZE,
|
||||
.compact_thresh = COMPACT_THRESH,
|
||||
.inline_max = INLINE_MAX,
|
||||
#ifdef LFS_MULTIVERSION
|
||||
.disk_version = DISK_VERSION,
|
||||
#endif
|
||||
@@ -1424,6 +1425,7 @@ static void run_powerloss_linear(
|
||||
.cache_size = CACHE_SIZE,
|
||||
.lookahead_size = LOOKAHEAD_SIZE,
|
||||
.compact_thresh = COMPACT_THRESH,
|
||||
.inline_max = INLINE_MAX,
|
||||
#ifdef LFS_MULTIVERSION
|
||||
.disk_version = DISK_VERSION,
|
||||
#endif
|
||||
@@ -1518,6 +1520,7 @@ static void run_powerloss_log(
|
||||
.cache_size = CACHE_SIZE,
|
||||
.lookahead_size = LOOKAHEAD_SIZE,
|
||||
.compact_thresh = COMPACT_THRESH,
|
||||
.inline_max = INLINE_MAX,
|
||||
#ifdef LFS_MULTIVERSION
|
||||
.disk_version = DISK_VERSION,
|
||||
#endif
|
||||
@@ -1610,6 +1613,7 @@ static void run_powerloss_cycles(
|
||||
.cache_size = CACHE_SIZE,
|
||||
.lookahead_size = LOOKAHEAD_SIZE,
|
||||
.compact_thresh = COMPACT_THRESH,
|
||||
.inline_max = INLINE_MAX,
|
||||
#ifdef LFS_MULTIVERSION
|
||||
.disk_version = DISK_VERSION,
|
||||
#endif
|
||||
@@ -1800,6 +1804,7 @@ static void run_powerloss_exhaustive(
|
||||
.cache_size = CACHE_SIZE,
|
||||
.lookahead_size = LOOKAHEAD_SIZE,
|
||||
.compact_thresh = COMPACT_THRESH,
|
||||
.inline_max = INLINE_MAX,
|
||||
#ifdef LFS_MULTIVERSION
|
||||
.disk_version = DISK_VERSION,
|
||||
#endif
|
||||
|
||||
@@ -89,12 +89,13 @@ intmax_t test_define(size_t define);
|
||||
#define CACHE_SIZE_i 6
|
||||
#define LOOKAHEAD_SIZE_i 7
|
||||
#define COMPACT_THRESH_i 8
|
||||
#define BLOCK_CYCLES_i 9
|
||||
#define ERASE_VALUE_i 10
|
||||
#define ERASE_CYCLES_i 11
|
||||
#define BADBLOCK_BEHAVIOR_i 12
|
||||
#define POWERLOSS_BEHAVIOR_i 13
|
||||
#define DISK_VERSION_i 14
|
||||
#define INLINE_MAX_i 9
|
||||
#define BLOCK_CYCLES_i 10
|
||||
#define ERASE_VALUE_i 11
|
||||
#define ERASE_CYCLES_i 12
|
||||
#define BADBLOCK_BEHAVIOR_i 13
|
||||
#define POWERLOSS_BEHAVIOR_i 14
|
||||
#define DISK_VERSION_i 15
|
||||
|
||||
#define READ_SIZE TEST_DEFINE(READ_SIZE_i)
|
||||
#define PROG_SIZE TEST_DEFINE(PROG_SIZE_i)
|
||||
@@ -105,6 +106,7 @@ intmax_t test_define(size_t define);
|
||||
#define CACHE_SIZE TEST_DEFINE(CACHE_SIZE_i)
|
||||
#define LOOKAHEAD_SIZE TEST_DEFINE(LOOKAHEAD_SIZE_i)
|
||||
#define COMPACT_THRESH TEST_DEFINE(COMPACT_THRESH_i)
|
||||
#define INLINE_MAX TEST_DEFINE(INLINE_MAX_i)
|
||||
#define BLOCK_CYCLES TEST_DEFINE(BLOCK_CYCLES_i)
|
||||
#define ERASE_VALUE TEST_DEFINE(ERASE_VALUE_i)
|
||||
#define ERASE_CYCLES TEST_DEFINE(ERASE_CYCLES_i)
|
||||
@@ -122,6 +124,7 @@ intmax_t test_define(size_t define);
|
||||
TEST_DEF(CACHE_SIZE, lfs_max(64,lfs_max(READ_SIZE,PROG_SIZE))) \
|
||||
TEST_DEF(LOOKAHEAD_SIZE, 16) \
|
||||
TEST_DEF(COMPACT_THRESH, 0) \
|
||||
TEST_DEF(INLINE_MAX, 0) \
|
||||
TEST_DEF(BLOCK_CYCLES, -1) \
|
||||
TEST_DEF(ERASE_VALUE, 0xff) \
|
||||
TEST_DEF(ERASE_CYCLES, 0) \
|
||||
@@ -130,7 +133,7 @@ intmax_t test_define(size_t define);
|
||||
TEST_DEF(DISK_VERSION, 0)
|
||||
|
||||
#define TEST_GEOMETRY_DEFINE_COUNT 4
|
||||
#define TEST_IMPLICIT_DEFINE_COUNT 15
|
||||
#define TEST_IMPLICIT_DEFINE_COUNT 16
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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);
|
||||
@@ -747,6 +755,11 @@ code = '''
|
||||
lfs_file_open(&lfs, &file, "potato",
|
||||
LFS_O_WRONLY | LFS_O_CREAT) => LFS_ERR_ISDIR;
|
||||
|
||||
lfs_file_open(&lfs, &file, "tacoto", LFS_O_WRONLY | LFS_O_CREAT) => 0;
|
||||
lfs_file_close(&lfs, &file) => 0;
|
||||
lfs_rename(&lfs, "tacoto", "potato") => LFS_ERR_ISDIR;
|
||||
lfs_rename(&lfs, "potato", "tacoto") => LFS_ERR_NOTDIR;
|
||||
|
||||
lfs_mkdir(&lfs, "/") => LFS_ERR_EXIST;
|
||||
lfs_file_open(&lfs, &file, "/",
|
||||
LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => LFS_ERR_EXIST;
|
||||
@@ -770,6 +783,10 @@ code = '''
|
||||
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||
assert(info.type == LFS_TYPE_DIR);
|
||||
assert(strcmp(info.name, "potato") == 0);
|
||||
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||
assert(info.type == LFS_TYPE_REG);
|
||||
assert(strcmp(info.name, "tacoto") == 0);
|
||||
assert(info.size == 0);
|
||||
lfs_dir_read(&lfs, &dir, &info) => 0;
|
||||
lfs_dir_close(&lfs, &dir) => 0;
|
||||
|
||||
@@ -790,6 +807,10 @@ code = '''
|
||||
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||
assert(info.type == LFS_TYPE_DIR);
|
||||
assert(strcmp(info.name, "potato") == 0);
|
||||
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||
assert(info.type == LFS_TYPE_REG);
|
||||
assert(strcmp(info.name, "tacoto") == 0);
|
||||
assert(info.size == 0);
|
||||
lfs_dir_read(&lfs, &dir, &info) => 0;
|
||||
lfs_dir_close(&lfs, &dir) => 0;
|
||||
lfs_unmount(&lfs) => 0;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
[cases.test_files_simple]
|
||||
defines.INLINE_MAX = [0, -1, 8]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
@@ -25,6 +26,7 @@ code = '''
|
||||
[cases.test_files_large]
|
||||
defines.SIZE = [32, 8192, 262144, 0, 7, 8193]
|
||||
defines.CHUNKSIZE = [31, 16, 33, 1, 1023]
|
||||
defines.INLINE_MAX = [0, -1, 8]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
@@ -67,6 +69,7 @@ code = '''
|
||||
defines.SIZE1 = [32, 8192, 131072, 0, 7, 8193]
|
||||
defines.SIZE2 = [32, 8192, 131072, 0, 7, 8193]
|
||||
defines.CHUNKSIZE = [31, 16, 1]
|
||||
defines.INLINE_MAX = [0, -1, 8]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
@@ -152,6 +155,7 @@ code = '''
|
||||
defines.SIZE1 = [32, 8192, 131072, 0, 7, 8193]
|
||||
defines.SIZE2 = [32, 8192, 131072, 0, 7, 8193]
|
||||
defines.CHUNKSIZE = [31, 16, 1]
|
||||
defines.INLINE_MAX = [0, -1, 8]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
@@ -232,6 +236,7 @@ code = '''
|
||||
defines.SIZE1 = [32, 8192, 131072, 0, 7, 8193]
|
||||
defines.SIZE2 = [32, 8192, 131072, 0, 7, 8193]
|
||||
defines.CHUNKSIZE = [31, 16, 1]
|
||||
defines.INLINE_MAX = [0, -1, 8]
|
||||
code = '''
|
||||
lfs_t lfs;
|
||||
lfs_format(&lfs, cfg) => 0;
|
||||
@@ -303,7 +308,12 @@ code = '''
|
||||
[cases.test_files_reentrant_write]
|
||||
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);
|
||||
@@ -354,11 +364,20 @@ code = '''
|
||||
[cases.test_files_reentrant_write_sync]
|
||||
defines = [
|
||||
# append (O(n))
|
||||
{MODE='LFS_O_APPEND', SIZE=[32, 0, 7, 2049], CHUNKSIZE=[31, 16, 65]},
|
||||
{MODE='LFS_O_APPEND',
|
||||
SIZE=[32, 0, 7, 2049],
|
||||
CHUNKSIZE=[31, 16, 65],
|
||||
INLINE_MAX=[0, -1, 8]},
|
||||
# truncate (O(n^2))
|
||||
{MODE='LFS_O_TRUNC', SIZE=[32, 0, 7, 200], CHUNKSIZE=[31, 16, 65]},
|
||||
{MODE='LFS_O_TRUNC',
|
||||
SIZE=[32, 0, 7, 200],
|
||||
CHUNKSIZE=[31, 16, 65],
|
||||
INLINE_MAX=[0, -1, 8]},
|
||||
# rewrite (O(n^2))
|
||||
{MODE=0, SIZE=[32, 0, 7, 200], CHUNKSIZE=[31, 16, 65]},
|
||||
{MODE=0,
|
||||
SIZE=[32, 0, 7, 200],
|
||||
CHUNKSIZE=[31, 16, 65],
|
||||
INLINE_MAX=[0, -1, 8]},
|
||||
]
|
||||
reentrant = true
|
||||
code = '''
|
||||
@@ -485,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