summaryrefslogtreecommitdiffstatshomepage
path: root/lib/littlefs/lfs2.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/littlefs/lfs2.c')
-rw-r--r--lib/littlefs/lfs2.c859
1 files changed, 537 insertions, 322 deletions
diff --git a/lib/littlefs/lfs2.c b/lib/littlefs/lfs2.c
index d89c42fd59..abdec19d7c 100644
--- a/lib/littlefs/lfs2.c
+++ b/lib/littlefs/lfs2.c
@@ -282,6 +282,21 @@ static int lfs2_bd_erase(lfs2_t *lfs2, lfs2_block_t block) {
/// Small type-level utilities ///
+
+// some operations on paths
+static inline lfs2_size_t lfs2_path_namelen(const char *path) {
+ return strcspn(path, "/");
+}
+
+static inline bool lfs2_path_islast(const char *path) {
+ lfs2_size_t namelen = lfs2_path_namelen(path);
+ return path[namelen + strspn(path + namelen, "/")] == '\0';
+}
+
+static inline bool lfs2_path_isdir(const char *path) {
+ return path[lfs2_path_namelen(path)] != '\0';
+}
+
// operations on block pairs
static inline void lfs2_pair_swap(lfs2_block_t pair[2]) {
lfs2_block_t t = pair[0];
@@ -389,18 +404,15 @@ struct lfs2_diskoff {
// operations on global state
static inline void lfs2_gstate_xor(lfs2_gstate_t *a, const lfs2_gstate_t *b) {
- for (int i = 0; i < 3; i++) {
- ((uint32_t*)a)[i] ^= ((const uint32_t*)b)[i];
- }
+ a->tag ^= b->tag;
+ a->pair[0] ^= b->pair[0];
+ a->pair[1] ^= b->pair[1];
}
static inline bool lfs2_gstate_iszero(const lfs2_gstate_t *a) {
- for (int i = 0; i < 3; i++) {
- if (((uint32_t*)a)[i] != 0) {
- return false;
- }
- }
- return true;
+ return a->tag == 0
+ && a->pair[0] == 0
+ && a->pair[1] == 0;
}
#ifndef LFS2_READONLY
@@ -550,9 +562,9 @@ static int lfs2_dir_compact(lfs2_t *lfs2,
lfs2_mdir_t *source, uint16_t begin, uint16_t end);
static lfs2_ssize_t lfs2_file_flushedwrite(lfs2_t *lfs2, lfs2_file_t *file,
const void *buffer, lfs2_size_t size);
-static lfs2_ssize_t lfs2_file_rawwrite(lfs2_t *lfs2, lfs2_file_t *file,
+static lfs2_ssize_t lfs2_file_write_(lfs2_t *lfs2, lfs2_file_t *file,
const void *buffer, lfs2_size_t size);
-static int lfs2_file_rawsync(lfs2_t *lfs2, lfs2_file_t *file);
+static int lfs2_file_sync_(lfs2_t *lfs2, lfs2_file_t *file);
static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file);
static int lfs2_file_flush(lfs2_t *lfs2, lfs2_file_t *file);
@@ -574,65 +586,72 @@ static int lfs21_traverse(lfs2_t *lfs2,
int (*cb)(void*, lfs2_block_t), void *data);
#endif
-static int lfs2_dir_rawrewind(lfs2_t *lfs2, lfs2_dir_t *dir);
+static int lfs2_dir_rewind_(lfs2_t *lfs2, lfs2_dir_t *dir);
static lfs2_ssize_t lfs2_file_flushedread(lfs2_t *lfs2, lfs2_file_t *file,
void *buffer, lfs2_size_t size);
-static lfs2_ssize_t lfs2_file_rawread(lfs2_t *lfs2, lfs2_file_t *file,
+static lfs2_ssize_t lfs2_file_read_(lfs2_t *lfs2, lfs2_file_t *file,
void *buffer, lfs2_size_t size);
-static int lfs2_file_rawclose(lfs2_t *lfs2, lfs2_file_t *file);
-static lfs2_soff_t lfs2_file_rawsize(lfs2_t *lfs2, lfs2_file_t *file);
+static int lfs2_file_close_(lfs2_t *lfs2, lfs2_file_t *file);
+static lfs2_soff_t lfs2_file_size_(lfs2_t *lfs2, lfs2_file_t *file);
-static lfs2_ssize_t lfs2_fs_rawsize(lfs2_t *lfs2);
-static int lfs2_fs_rawtraverse(lfs2_t *lfs2,
+static lfs2_ssize_t lfs2_fs_size_(lfs2_t *lfs2);
+static int lfs2_fs_traverse_(lfs2_t *lfs2,
int (*cb)(void *data, lfs2_block_t block), void *data,
bool includeorphans);
static int lfs2_deinit(lfs2_t *lfs2);
-static int lfs2_rawunmount(lfs2_t *lfs2);
+static int lfs2_unmount_(lfs2_t *lfs2);
/// Block allocator ///
+
+// allocations should call this when all allocated blocks are committed to
+// the filesystem
+//
+// after a checkpoint, the block allocator may realloc any untracked blocks
+static void lfs2_alloc_ckpoint(lfs2_t *lfs2) {
+ lfs2->lookahead.ckpoint = lfs2->block_count;
+}
+
+// drop the lookahead buffer, this is done during mounting and failed
+// traversals in order to avoid invalid lookahead state
+static void lfs2_alloc_drop(lfs2_t *lfs2) {
+ lfs2->lookahead.size = 0;
+ lfs2->lookahead.next = 0;
+ lfs2_alloc_ckpoint(lfs2);
+}
+
#ifndef LFS2_READONLY
static int lfs2_alloc_lookahead(void *p, lfs2_block_t block) {
lfs2_t *lfs2 = (lfs2_t*)p;
- lfs2_block_t off = ((block - lfs2->free.off)
+ lfs2_block_t off = ((block - lfs2->lookahead.start)
+ lfs2->block_count) % lfs2->block_count;
- if (off < lfs2->free.size) {
- lfs2->free.buffer[off / 32] |= 1U << (off % 32);
+ if (off < lfs2->lookahead.size) {
+ lfs2->lookahead.buffer[off / 8] |= 1U << (off % 8);
}
return 0;
}
#endif
-// indicate allocated blocks have been committed into the filesystem, this
-// is to prevent blocks from being garbage collected in the middle of a
-// commit operation
-static void lfs2_alloc_ack(lfs2_t *lfs2) {
- lfs2->free.ack = lfs2->block_count;
-}
-
-// drop the lookahead buffer, this is done during mounting and failed
-// traversals in order to avoid invalid lookahead state
-static void lfs2_alloc_drop(lfs2_t *lfs2) {
- lfs2->free.size = 0;
- lfs2->free.i = 0;
- lfs2_alloc_ack(lfs2);
-}
-
#ifndef LFS2_READONLY
-static int lfs2_fs_rawgc(lfs2_t *lfs2) {
- // Move free offset at the first unused block (lfs2->free.i)
- // lfs2->free.i is equal lfs2->free.size when all blocks are used
- lfs2->free.off = (lfs2->free.off + lfs2->free.i) % lfs2->block_count;
- lfs2->free.size = lfs2_min(8*lfs2->cfg->lookahead_size, lfs2->free.ack);
- lfs2->free.i = 0;
+static int lfs2_alloc_scan(lfs2_t *lfs2) {
+ // move lookahead buffer to the first unused block
+ //
+ // note we limit the lookahead buffer to at most the amount of blocks
+ // checkpointed, this prevents the math in lfs2_alloc from underflowing
+ lfs2->lookahead.start = (lfs2->lookahead.start + lfs2->lookahead.next)
+ % lfs2->block_count;
+ lfs2->lookahead.next = 0;
+ lfs2->lookahead.size = lfs2_min(
+ 8*lfs2->cfg->lookahead_size,
+ lfs2->lookahead.ckpoint);
// find mask of free blocks from tree
- memset(lfs2->free.buffer, 0, lfs2->cfg->lookahead_size);
- int err = lfs2_fs_rawtraverse(lfs2, lfs2_alloc_lookahead, lfs2, true);
+ memset(lfs2->lookahead.buffer, 0, lfs2->cfg->lookahead_size);
+ int err = lfs2_fs_traverse_(lfs2, lfs2_alloc_lookahead, lfs2, true);
if (err) {
lfs2_alloc_drop(lfs2);
return err;
@@ -645,36 +664,49 @@ static int lfs2_fs_rawgc(lfs2_t *lfs2) {
#ifndef LFS2_READONLY
static int lfs2_alloc(lfs2_t *lfs2, lfs2_block_t *block) {
while (true) {
- while (lfs2->free.i != lfs2->free.size) {
- lfs2_block_t off = lfs2->free.i;
- lfs2->free.i += 1;
- lfs2->free.ack -= 1;
-
- if (!(lfs2->free.buffer[off / 32] & (1U << (off % 32)))) {
+ // scan our lookahead buffer for free blocks
+ while (lfs2->lookahead.next < lfs2->lookahead.size) {
+ if (!(lfs2->lookahead.buffer[lfs2->lookahead.next / 8]
+ & (1U << (lfs2->lookahead.next % 8)))) {
// found a free block
- *block = (lfs2->free.off + off) % lfs2->block_count;
-
- // eagerly find next off so an alloc ack can
- // discredit old lookahead blocks
- while (lfs2->free.i != lfs2->free.size &&
- (lfs2->free.buffer[lfs2->free.i / 32]
- & (1U << (lfs2->free.i % 32)))) {
- lfs2->free.i += 1;
- lfs2->free.ack -= 1;
+ *block = (lfs2->lookahead.start + lfs2->lookahead.next)
+ % lfs2->block_count;
+
+ // eagerly find next free block to maximize how many blocks
+ // lfs2_alloc_ckpoint makes available for scanning
+ while (true) {
+ lfs2->lookahead.next += 1;
+ lfs2->lookahead.ckpoint -= 1;
+
+ if (lfs2->lookahead.next >= lfs2->lookahead.size
+ || !(lfs2->lookahead.buffer[lfs2->lookahead.next / 8]
+ & (1U << (lfs2->lookahead.next % 8)))) {
+ return 0;
+ }
}
-
- return 0;
}
+
+ lfs2->lookahead.next += 1;
+ lfs2->lookahead.ckpoint -= 1;
}
- // check if we have looked at all blocks since last ack
- if (lfs2->free.ack == 0) {
- LFS2_ERROR("No more free space %"PRIu32,
- lfs2->free.i + lfs2->free.off);
+ // In order to keep our block allocator from spinning forever when our
+ // filesystem is full, we mark points where there are no in-flight
+ // allocations with a checkpoint before starting a set of allocations.
+ //
+ // If we've looked at all blocks since the last checkpoint, we report
+ // the filesystem as out of storage.
+ //
+ if (lfs2->lookahead.ckpoint <= 0) {
+ LFS2_ERROR("No more free space 0x%"PRIx32,
+ (lfs2->lookahead.start + lfs2->lookahead.next)
+ % lfs2->block_count);
return LFS2_ERR_NOSPC;
}
- int err = lfs2_fs_rawgc(lfs2);
+ // No blocks in our lookahead buffer, we need to scan the filesystem for
+ // unused blocks in the next lookahead window.
+ int err = lfs2_alloc_scan(lfs2);
if(err) {
return err;
}
@@ -690,11 +722,14 @@ static lfs2_stag_t lfs2_dir_getslice(lfs2_t *lfs2, const lfs2_mdir_t *dir,
lfs2_tag_t ntag = dir->etag;
lfs2_stag_t gdiff = 0;
+ // synthetic moves
if (lfs2_gstate_hasmovehere(&lfs2->gdisk, dir->pair) &&
- lfs2_tag_id(gmask) != 0 &&
- lfs2_tag_id(lfs2->gdisk.tag) <= lfs2_tag_id(gtag)) {
- // synthetic moves
- gdiff -= LFS2_MKTAG(0, 1, 0);
+ lfs2_tag_id(gmask) != 0) {
+ if (lfs2_tag_id(lfs2->gdisk.tag) == lfs2_tag_id(gtag)) {
+ return LFS2_ERR_NOENT;
+ } 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)
@@ -1438,32 +1473,46 @@ static int lfs2_dir_find_match(void *data,
return LFS2_CMP_EQ;
}
+// lfs2_dir_find tries to set path and id even if file is not found
+//
+// returns:
+// - 0 if file is found
+// - LFS2_ERR_NOENT if file or parent is not found
+// - LFS2_ERR_NOTDIR if parent is not a dir
static lfs2_stag_t lfs2_dir_find(lfs2_t *lfs2, lfs2_mdir_t *dir,
const char **path, uint16_t *id) {
// we reduce path to a single name if we can find it
const char *name = *path;
- if (id) {
- *id = 0x3ff;
- }
// default to root dir
lfs2_stag_t tag = LFS2_MKTAG(LFS2_TYPE_DIR, 0x3ff, 0);
dir->tail[0] = lfs2->root[0];
dir->tail[1] = lfs2->root[1];
+ // empty paths are not allowed
+ if (*name == '\0') {
+ return LFS2_ERR_INVAL;
+ }
+
while (true) {
nextname:
- // skip slashes
- name += strspn(name, "/");
+ // skip slashes if we're a directory
+ if (lfs2_tag_type3(tag) == LFS2_TYPE_DIR) {
+ name += strspn(name, "/");
+ }
lfs2_size_t namelen = strcspn(name, "/");
- // skip '.' and root '..'
- if ((namelen == 1 && memcmp(name, ".", 1) == 0) ||
- (namelen == 2 && memcmp(name, "..", 2) == 0)) {
+ // skip '.'
+ if (namelen == 1 && memcmp(name, ".", 1) == 0) {
name += namelen;
goto nextname;
}
+ // error on unmatched '..', trying to go above root?
+ if (namelen == 2 && memcmp(name, "..", 2) == 0) {
+ return LFS2_ERR_INVAL;
+ }
+
// skip if matched by '..' in name
const char *suffix = name + namelen;
lfs2_size_t sufflen;
@@ -1475,7 +1524,9 @@ nextname:
break;
}
- if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) {
+ if (sufflen == 1 && memcmp(suffix, ".", 1) == 0) {
+ // noop
+ } else if (sufflen == 2 && memcmp(suffix, "..", 2) == 0) {
depth -= 1;
if (depth == 0) {
name = suffix + sufflen;
@@ -1489,14 +1540,14 @@ nextname:
}
// found path
- if (name[0] == '\0') {
+ if (*name == '\0') {
return tag;
}
// update what we've found so far
*path = name;
- // only continue if we hit a directory
+ // only continue if we're a directory
if (lfs2_tag_type3(tag) != LFS2_TYPE_DIR) {
return LFS2_ERR_NOTDIR;
}
@@ -1516,8 +1567,7 @@ nextname:
tag = lfs2_dir_fetchmatch(lfs2, dir, dir->tail,
LFS2_MKTAG(0x780, 0, 0),
LFS2_MKTAG(LFS2_TYPE_NAME, 0, namelen),
- // are we last name?
- (strchr(name, '/') == NULL) ? id : NULL,
+ id,
lfs2_dir_find_match, &(struct lfs2_dir_find_match){
lfs2, name, namelen});
if (tag < 0) {
@@ -2105,13 +2155,14 @@ static int lfs2_dir_splittingcompact(lfs2_t *lfs2, lfs2_mdir_t *dir,
// And we cap at half a block to avoid degenerate cases with
// nearly-full metadata blocks.
//
+ lfs2_size_t metadata_max = (lfs2->cfg->metadata_max)
+ ? lfs2->cfg->metadata_max
+ : lfs2->cfg->block_size;
if (end - split < 0xff
&& size <= lfs2_min(
- lfs2->cfg->block_size - 40,
+ metadata_max - 40,
lfs2_alignup(
- (lfs2->cfg->metadata_max
- ? lfs2->cfg->metadata_max
- : lfs2->cfg->block_size)/2,
+ metadata_max/2,
lfs2->cfg->prog_size))) {
break;
}
@@ -2146,14 +2197,16 @@ static int lfs2_dir_splittingcompact(lfs2_t *lfs2, lfs2_mdir_t *dir,
&& lfs2_pair_cmp(dir->pair, (const lfs2_block_t[2]){0, 1}) == 0) {
// oh no! we're writing too much to the superblock,
// should we expand?
- lfs2_ssize_t size = lfs2_fs_rawsize(lfs2);
+ lfs2_ssize_t size = lfs2_fs_size_(lfs2);
if (size < 0) {
return size;
}
- // do we have extra space? littlefs can't reclaim this space
- // by itself, so expand cautiously
- if ((lfs2_size_t)size < lfs2->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 (lfs2->block_count - size > lfs2->block_count/8) {
LFS2_DEBUG("Expanding superblock at rev %"PRIu32, dir->rev);
int err = lfs2_dir_split(lfs2, dir, attrs, attrcount,
source, begin, end);
@@ -2166,7 +2219,8 @@ static int lfs2_dir_splittingcompact(lfs2_t *lfs2, lfs2_mdir_t *dir,
// we can do, we'll error later if we've become frozen
LFS2_WARN("Unable to expand superblock");
} else {
- end = begin;
+ // duplicate the superblock entry into the new superblock
+ end = 1;
}
}
}
@@ -2312,7 +2366,8 @@ fixmlist:;
if (d->m.pair != pair) {
for (int i = 0; i < attrcount; i++) {
if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE &&
- d->id == lfs2_tag_id(attrs[i].tag)) {
+ d->id == lfs2_tag_id(attrs[i].tag) &&
+ d->type != LFS2_TYPE_DIR) {
d->m.pair[0] = LFS2_BLOCK_NULL;
d->m.pair[1] = LFS2_BLOCK_NULL;
} else if (lfs2_tag_type3(attrs[i].tag) == LFS2_TYPE_DELETE &&
@@ -2333,7 +2388,9 @@ fixmlist:;
while (d->id >= d->m.count && d->m.split) {
// we split and id is on tail now
- d->id -= d->m.count;
+ if (lfs2_pair_cmp(d->m.tail, lfs2->root) != 0) {
+ d->id -= d->m.count;
+ }
int err = lfs2_dir_fetch(lfs2, &d->m, d->m.tail);
if (err) {
return err;
@@ -2499,7 +2556,7 @@ static int lfs2_dir_orphaningcommit(lfs2_t *lfs2, lfs2_mdir_t *dir,
if (err != LFS2_ERR_NOENT) {
if (lfs2_gstate_hasorphans(&lfs2->gstate)) {
// next step, clean up orphans
- err = lfs2_fs_preporphans(lfs2, -hasparent);
+ err = lfs2_fs_preporphans(lfs2, -(int8_t)hasparent);
if (err) {
return err;
}
@@ -2564,7 +2621,7 @@ static int lfs2_dir_commit(lfs2_t *lfs2, lfs2_mdir_t *dir,
/// Top level directory operations ///
#ifndef LFS2_READONLY
-static int lfs2_rawmkdir(lfs2_t *lfs2, const char *path) {
+static int lfs2_mkdir_(lfs2_t *lfs2, const char *path) {
// deorphan if we haven't yet, needed at most once after poweron
int err = lfs2_fs_forceconsistency(lfs2);
if (err) {
@@ -2575,18 +2632,18 @@ static int lfs2_rawmkdir(lfs2_t *lfs2, const char *path) {
cwd.next = lfs2->mlist;
uint16_t id;
err = lfs2_dir_find(lfs2, &cwd.m, &path, &id);
- if (!(err == LFS2_ERR_NOENT && id != 0x3ff)) {
+ if (!(err == LFS2_ERR_NOENT && lfs2_path_islast(path))) {
return (err < 0) ? err : LFS2_ERR_EXIST;
}
// check that name fits
- lfs2_size_t nlen = strlen(path);
+ lfs2_size_t nlen = lfs2_path_namelen(path);
if (nlen > lfs2->name_max) {
return LFS2_ERR_NAMETOOLONG;
}
// build up new directory
- lfs2_alloc_ack(lfs2);
+ lfs2_alloc_ckpoint(lfs2);
lfs2_mdir_t dir;
err = lfs2_dir_alloc(lfs2, &dir);
if (err) {
@@ -2660,7 +2717,7 @@ static int lfs2_rawmkdir(lfs2_t *lfs2, const char *path) {
}
#endif
-static int lfs2_dir_rawopen(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) {
+static int lfs2_dir_open_(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) {
lfs2_stag_t tag = lfs2_dir_find(lfs2, &dir->m, &path, NULL);
if (tag < 0) {
return tag;
@@ -2704,14 +2761,14 @@ static int lfs2_dir_rawopen(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) {
return 0;
}
-static int lfs2_dir_rawclose(lfs2_t *lfs2, lfs2_dir_t *dir) {
+static int lfs2_dir_close_(lfs2_t *lfs2, lfs2_dir_t *dir) {
// remove from list of mdirs
lfs2_mlist_remove(lfs2, (struct lfs2_mlist *)dir);
return 0;
}
-static int lfs2_dir_rawread(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) {
+static int lfs2_dir_read_(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) {
memset(info, 0, sizeof(*info));
// special offset for '.' and '..'
@@ -2756,9 +2813,9 @@ static int lfs2_dir_rawread(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *inf
return true;
}
-static int lfs2_dir_rawseek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) {
+static int lfs2_dir_seek_(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) {
// simply walk from head dir
- int err = lfs2_dir_rawrewind(lfs2, dir);
+ int err = lfs2_dir_rewind_(lfs2, dir);
if (err) {
return err;
}
@@ -2793,12 +2850,12 @@ static int lfs2_dir_rawseek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) {
return 0;
}
-static lfs2_soff_t lfs2_dir_rawtell(lfs2_t *lfs2, lfs2_dir_t *dir) {
+static lfs2_soff_t lfs2_dir_tell_(lfs2_t *lfs2, lfs2_dir_t *dir) {
(void)lfs2;
return dir->pos;
}
-static int lfs2_dir_rawrewind(lfs2_t *lfs2, lfs2_dir_t *dir) {
+static int lfs2_dir_rewind_(lfs2_t *lfs2, lfs2_dir_t *dir) {
// reload the head dir
int err = lfs2_dir_fetch(lfs2, &dir->m, dir->head);
if (err) {
@@ -3004,7 +3061,7 @@ static int lfs2_ctz_traverse(lfs2_t *lfs2,
/// Top level file operations ///
-static int lfs2_file_rawopencfg(lfs2_t *lfs2, lfs2_file_t *file,
+static int lfs2_file_opencfg_(lfs2_t *lfs2, lfs2_file_t *file,
const char *path, int flags,
const struct lfs2_file_config *cfg) {
#ifndef LFS2_READONLY
@@ -3029,7 +3086,7 @@ static int lfs2_file_rawopencfg(lfs2_t *lfs2, lfs2_file_t *file,
// allocate entry for file if it doesn't exist
lfs2_stag_t tag = lfs2_dir_find(lfs2, &file->m, &path, &file->id);
- if (tag < 0 && !(tag == LFS2_ERR_NOENT && file->id != 0x3ff)) {
+ if (tag < 0 && !(tag == LFS2_ERR_NOENT && lfs2_path_islast(path))) {
err = tag;
goto cleanup;
}
@@ -3049,8 +3106,14 @@ static int lfs2_file_rawopencfg(lfs2_t *lfs2, lfs2_file_t *file,
goto cleanup;
}
+ // don't allow trailing slashes
+ if (lfs2_path_isdir(path)) {
+ err = LFS2_ERR_NOTDIR;
+ goto cleanup;
+ }
+
// check that name fits
- lfs2_size_t nlen = strlen(path);
+ lfs2_size_t nlen = lfs2_path_namelen(path);
if (nlen > lfs2->name_max) {
err = LFS2_ERR_NAMETOOLONG;
goto cleanup;
@@ -3166,22 +3229,22 @@ cleanup:
#ifndef LFS2_READONLY
file->flags |= LFS2_F_ERRED;
#endif
- lfs2_file_rawclose(lfs2, file);
+ lfs2_file_close_(lfs2, file);
return err;
}
#ifndef LFS2_NO_MALLOC
-static int lfs2_file_rawopen(lfs2_t *lfs2, lfs2_file_t *file,
+static int lfs2_file_open_(lfs2_t *lfs2, lfs2_file_t *file,
const char *path, int flags) {
static const struct lfs2_file_config defaults = {0};
- int err = lfs2_file_rawopencfg(lfs2, file, path, flags, &defaults);
+ int err = lfs2_file_opencfg_(lfs2, file, path, flags, &defaults);
return err;
}
#endif
-static int lfs2_file_rawclose(lfs2_t *lfs2, lfs2_file_t *file) {
+static int lfs2_file_close_(lfs2_t *lfs2, lfs2_file_t *file) {
#ifndef LFS2_READONLY
- int err = lfs2_file_rawsync(lfs2, file);
+ int err = lfs2_file_sync_(lfs2, file);
#else
int err = 0;
#endif
@@ -3272,7 +3335,7 @@ relocate:
#ifndef LFS2_READONLY
static int lfs2_file_outline(lfs2_t *lfs2, lfs2_file_t *file) {
file->off = file->pos;
- lfs2_alloc_ack(lfs2);
+ lfs2_alloc_ckpoint(lfs2);
int err = lfs2_file_relocate(lfs2, file);
if (err) {
return err;
@@ -3364,7 +3427,7 @@ relocate:
}
#ifndef LFS2_READONLY
-static int lfs2_file_rawsync(lfs2_t *lfs2, lfs2_file_t *file) {
+static int lfs2_file_sync_(lfs2_t *lfs2, lfs2_file_t *file) {
if (file->flags & LFS2_F_ERRED) {
// it's not safe to do anything if our file errored
return 0;
@@ -3379,6 +3442,15 @@ static int lfs2_file_rawsync(lfs2_t *lfs2, lfs2_file_t *file) {
if ((file->flags & LFS2_F_DIRTY) &&
!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
uint16_t type;
const void *buffer;
@@ -3477,7 +3549,7 @@ static lfs2_ssize_t lfs2_file_flushedread(lfs2_t *lfs2, lfs2_file_t *file,
return size;
}
-static lfs2_ssize_t lfs2_file_rawread(lfs2_t *lfs2, lfs2_file_t *file,
+static lfs2_ssize_t lfs2_file_read_(lfs2_t *lfs2, lfs2_file_t *file,
void *buffer, lfs2_size_t size) {
LFS2_ASSERT((file->flags & LFS2_O_RDONLY) == LFS2_O_RDONLY);
@@ -3502,11 +3574,7 @@ static lfs2_ssize_t lfs2_file_flushedwrite(lfs2_t *lfs2, lfs2_file_t *file,
lfs2_size_t nsize = size;
if ((file->flags & LFS2_F_INLINE) &&
- lfs2_max(file->pos+nsize, file->ctz.size) >
- lfs2_min(0x3fe, lfs2_min(
- lfs2->cfg->cache_size,
- (lfs2->cfg->metadata_max ?
- lfs2->cfg->metadata_max : lfs2->cfg->block_size) / 8))) {
+ lfs2_max(file->pos+nsize, file->ctz.size) > lfs2->inline_max) {
// inline file doesn't fit anymore
int err = lfs2_file_outline(lfs2, file);
if (err) {
@@ -3535,7 +3603,7 @@ static lfs2_ssize_t lfs2_file_flushedwrite(lfs2_t *lfs2, lfs2_file_t *file,
}
// extend file with new blocks
- lfs2_alloc_ack(lfs2);
+ lfs2_alloc_ckpoint(lfs2);
int err = lfs2_ctz_extend(lfs2, &file->cache, &lfs2->rcache,
file->block, file->pos,
&file->block, &file->off);
@@ -3578,13 +3646,13 @@ relocate:
data += diff;
nsize -= diff;
- lfs2_alloc_ack(lfs2);
+ lfs2_alloc_ckpoint(lfs2);
}
return size;
}
-static lfs2_ssize_t lfs2_file_rawwrite(lfs2_t *lfs2, lfs2_file_t *file,
+static lfs2_ssize_t lfs2_file_write_(lfs2_t *lfs2, lfs2_file_t *file,
const void *buffer, lfs2_size_t size) {
LFS2_ASSERT((file->flags & LFS2_O_WRONLY) == LFS2_O_WRONLY);
@@ -3628,25 +3696,19 @@ static lfs2_ssize_t lfs2_file_rawwrite(lfs2_t *lfs2, lfs2_file_t *file,
}
#endif
-static lfs2_soff_t lfs2_file_rawseek(lfs2_t *lfs2, lfs2_file_t *file,
+static lfs2_soff_t lfs2_file_seek_(lfs2_t *lfs2, lfs2_file_t *file,
lfs2_soff_t off, int whence) {
// find new pos
+ //
+ // fortunately for us, littlefs is limited to 31-bit file sizes, so we
+ // don't have to worry too much about integer overflow
lfs2_off_t npos = file->pos;
if (whence == LFS2_SEEK_SET) {
npos = off;
} else if (whence == LFS2_SEEK_CUR) {
- if ((lfs2_soff_t)file->pos + off < 0) {
- return LFS2_ERR_INVAL;
- } else {
- npos = file->pos + off;
- }
+ npos = file->pos + (lfs2_off_t)off;
} else if (whence == LFS2_SEEK_END) {
- lfs2_soff_t res = lfs2_file_rawsize(lfs2, file) + off;
- if (res < 0) {
- return LFS2_ERR_INVAL;
- } else {
- npos = res;
- }
+ npos = (lfs2_off_t)lfs2_file_size_(lfs2, file) + (lfs2_off_t)off;
}
if (npos > lfs2->file_max) {
@@ -3661,13 +3723,8 @@ static lfs2_soff_t lfs2_file_rawseek(lfs2_t *lfs2, lfs2_file_t *file,
// if we're only reading and our new offset is still in the file's cache
// we can avoid flushing and needing to reread the data
- if (
-#ifndef LFS2_READONLY
- !(file->flags & LFS2_F_WRITING)
-#else
- true
-#endif
- ) {
+ if ((file->flags & LFS2_F_READING)
+ && file->off != lfs2->cfg->block_size) {
int oindex = lfs2_ctz_index(lfs2, &(lfs2_off_t){file->pos});
lfs2_off_t noff = npos;
int nindex = lfs2_ctz_index(lfs2, &noff);
@@ -3692,7 +3749,7 @@ static lfs2_soff_t lfs2_file_rawseek(lfs2_t *lfs2, lfs2_file_t *file,
}
#ifndef LFS2_READONLY
-static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) {
+static int lfs2_file_truncate_(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) {
LFS2_ASSERT((file->flags & LFS2_O_WRONLY) == LFS2_O_WRONLY);
if (size > LFS2_FILE_MAX) {
@@ -3700,15 +3757,12 @@ static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t siz
}
lfs2_off_t pos = file->pos;
- lfs2_off_t oldsize = lfs2_file_rawsize(lfs2, file);
+ lfs2_off_t oldsize = lfs2_file_size_(lfs2, file);
if (size < oldsize) {
// revert to inline file?
- if (size <= lfs2_min(0x3fe, lfs2_min(
- lfs2->cfg->cache_size,
- (lfs2->cfg->metadata_max ?
- lfs2->cfg->metadata_max : lfs2->cfg->block_size) / 8))) {
+ if (size <= lfs2->inline_max) {
// flush+seek to head
- lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, 0, LFS2_SEEK_SET);
+ lfs2_soff_t res = lfs2_file_seek_(lfs2, file, 0, LFS2_SEEK_SET);
if (res < 0) {
return (int)res;
}
@@ -3753,14 +3807,14 @@ static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t siz
}
} else if (size > oldsize) {
// flush+seek if not already at end
- lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, 0, LFS2_SEEK_END);
+ lfs2_soff_t res = lfs2_file_seek_(lfs2, file, 0, LFS2_SEEK_END);
if (res < 0) {
return (int)res;
}
// fill with zeros
while (file->pos < size) {
- res = lfs2_file_rawwrite(lfs2, file, &(uint8_t){0}, 1);
+ res = lfs2_file_write_(lfs2, file, &(uint8_t){0}, 1);
if (res < 0) {
return (int)res;
}
@@ -3768,7 +3822,7 @@ static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t siz
}
// restore pos
- lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, pos, LFS2_SEEK_SET);
+ lfs2_soff_t res = lfs2_file_seek_(lfs2, file, pos, LFS2_SEEK_SET);
if (res < 0) {
return (int)res;
}
@@ -3777,13 +3831,13 @@ static int lfs2_file_rawtruncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t siz
}
#endif
-static lfs2_soff_t lfs2_file_rawtell(lfs2_t *lfs2, lfs2_file_t *file) {
+static lfs2_soff_t lfs2_file_tell_(lfs2_t *lfs2, lfs2_file_t *file) {
(void)lfs2;
return file->pos;
}
-static int lfs2_file_rawrewind(lfs2_t *lfs2, lfs2_file_t *file) {
- lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, 0, LFS2_SEEK_SET);
+static int lfs2_file_rewind_(lfs2_t *lfs2, lfs2_file_t *file) {
+ lfs2_soff_t res = lfs2_file_seek_(lfs2, file, 0, LFS2_SEEK_SET);
if (res < 0) {
return (int)res;
}
@@ -3791,7 +3845,7 @@ static int lfs2_file_rawrewind(lfs2_t *lfs2, lfs2_file_t *file) {
return 0;
}
-static lfs2_soff_t lfs2_file_rawsize(lfs2_t *lfs2, lfs2_file_t *file) {
+static lfs2_soff_t lfs2_file_size_(lfs2_t *lfs2, lfs2_file_t *file) {
(void)lfs2;
#ifndef LFS2_READONLY
@@ -3805,18 +3859,24 @@ static lfs2_soff_t lfs2_file_rawsize(lfs2_t *lfs2, lfs2_file_t *file) {
/// General fs operations ///
-static int lfs2_rawstat(lfs2_t *lfs2, const char *path, struct lfs2_info *info) {
+static int lfs2_stat_(lfs2_t *lfs2, const char *path, struct lfs2_info *info) {
lfs2_mdir_t cwd;
lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL);
if (tag < 0) {
return (int)tag;
}
+ // only allow trailing slashes on dirs
+ if (strchr(path, '/') != NULL
+ && lfs2_tag_type3(tag) != LFS2_TYPE_DIR) {
+ return LFS2_ERR_NOTDIR;
+ }
+
return lfs2_dir_getinfo(lfs2, &cwd, lfs2_tag_id(tag), info);
}
#ifndef LFS2_READONLY
-static int lfs2_rawremove(lfs2_t *lfs2, const char *path) {
+static int lfs2_remove_(lfs2_t *lfs2, const char *path) {
// deorphan if we haven't yet, needed at most once after poweron
int err = lfs2_fs_forceconsistency(lfs2);
if (err) {
@@ -3872,7 +3932,9 @@ static int lfs2_rawremove(lfs2_t *lfs2, const char *path) {
}
lfs2->mlist = dir.next;
- if (lfs2_tag_type3(tag) == LFS2_TYPE_DIR) {
+ if (lfs2_gstate_hasorphans(&lfs2->gstate)) {
+ LFS2_ASSERT(lfs2_tag_type3(tag) == LFS2_TYPE_DIR);
+
// fix orphan
err = lfs2_fs_preporphans(lfs2, -1);
if (err) {
@@ -3895,7 +3957,7 @@ static int lfs2_rawremove(lfs2_t *lfs2, const char *path) {
#endif
#ifndef LFS2_READONLY
-static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
+static int lfs2_rename_(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
// deorphan if we haven't yet, needed at most once after poweron
int err = lfs2_fs_forceconsistency(lfs2);
if (err) {
@@ -3914,7 +3976,7 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath
uint16_t newid;
lfs2_stag_t prevtag = lfs2_dir_find(lfs2, &newcwd, &newpath, &newid);
if ((prevtag < 0 || lfs2_tag_id(prevtag) == 0x3ff) &&
- !(prevtag == LFS2_ERR_NOENT && newid != 0x3ff)) {
+ !(prevtag == LFS2_ERR_NOENT && lfs2_path_islast(newpath))) {
return (prevtag < 0) ? (int)prevtag : LFS2_ERR_INVAL;
}
@@ -3925,8 +3987,14 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath
struct lfs2_mlist prevdir;
prevdir.next = lfs2->mlist;
if (prevtag == LFS2_ERR_NOENT) {
+ // if we're a file, don't allow trailing slashes
+ if (lfs2_path_isdir(newpath)
+ && lfs2_tag_type3(oldtag) != LFS2_TYPE_DIR) {
+ return LFS2_ERR_NOTDIR;
+ }
+
// check that name fits
- lfs2_size_t nlen = strlen(newpath);
+ lfs2_size_t nlen = lfs2_path_namelen(newpath);
if (nlen > lfs2->name_max) {
return LFS2_ERR_NAMETOOLONG;
}
@@ -3938,7 +4006,9 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath
newoldid += 1;
}
} else if (lfs2_tag_type3(prevtag) != lfs2_tag_type3(oldtag)) {
- return LFS2_ERR_ISDIR;
+ return (lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR)
+ ? LFS2_ERR_ISDIR
+ : LFS2_ERR_NOTDIR;
} else if (samepair && newid == newoldid) {
// we're renaming to ourselves??
return 0;
@@ -3984,7 +4054,8 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath
{LFS2_MKTAG_IF(prevtag != LFS2_ERR_NOENT,
LFS2_TYPE_DELETE, newid, 0), NULL},
{LFS2_MKTAG(LFS2_TYPE_CREATE, newid, 0), NULL},
- {LFS2_MKTAG(lfs2_tag_type3(oldtag), newid, strlen(newpath)), newpath},
+ {LFS2_MKTAG(lfs2_tag_type3(oldtag),
+ newid, lfs2_path_namelen(newpath)), newpath},
{LFS2_MKTAG(LFS2_FROM_MOVE, newid, lfs2_tag_id(oldtag)), &oldcwd},
{LFS2_MKTAG_IF(samepair,
LFS2_TYPE_DELETE, newoldid, 0), NULL}));
@@ -4007,8 +4078,10 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath
}
lfs2->mlist = prevdir.next;
- if (prevtag != LFS2_ERR_NOENT
- && lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR) {
+ if (lfs2_gstate_hasorphans(&lfs2->gstate)) {
+ LFS2_ASSERT(prevtag != LFS2_ERR_NOENT
+ && lfs2_tag_type3(prevtag) == LFS2_TYPE_DIR);
+
// fix orphan
err = lfs2_fs_preporphans(lfs2, -1);
if (err) {
@@ -4030,7 +4103,7 @@ static int lfs2_rawrename(lfs2_t *lfs2, const char *oldpath, const char *newpath
}
#endif
-static lfs2_ssize_t lfs2_rawgetattr(lfs2_t *lfs2, const char *path,
+static lfs2_ssize_t lfs2_getattr_(lfs2_t *lfs2, const char *path,
uint8_t type, void *buffer, lfs2_size_t size) {
lfs2_mdir_t cwd;
lfs2_stag_t tag = lfs2_dir_find(lfs2, &cwd, &path, NULL);
@@ -4088,7 +4161,7 @@ static int lfs2_commitattr(lfs2_t *lfs2, const char *path,
#endif
#ifndef LFS2_READONLY
-static int lfs2_rawsetattr(lfs2_t *lfs2, const char *path,
+static int lfs2_setattr_(lfs2_t *lfs2, const char *path,
uint8_t type, const void *buffer, lfs2_size_t size) {
if (size > lfs2->attr_max) {
return LFS2_ERR_NOSPC;
@@ -4099,13 +4172,28 @@ static int lfs2_rawsetattr(lfs2_t *lfs2, const char *path,
#endif
#ifndef LFS2_READONLY
-static int lfs2_rawremoveattr(lfs2_t *lfs2, const char *path, uint8_t type) {
+static int lfs2_removeattr_(lfs2_t *lfs2, const char *path, uint8_t type) {
return lfs2_commitattr(lfs2, path, type, NULL, 0x3ff);
}
#endif
/// Filesystem operations ///
+
+// compile time checks, see lfs2.h for why these limits exist
+#if LFS2_NAME_MAX > 1022
+#error "Invalid LFS2_NAME_MAX, must be <= 1022"
+#endif
+
+#if LFS2_FILE_MAX > 2147483647
+#error "Invalid LFS2_FILE_MAX, must be <= 2147483647"
+#endif
+
+#if LFS2_ATTR_MAX > 1022
+#error "Invalid LFS2_ATTR_MAX, must be <= 1022"
+#endif
+
+// common filesystem initialization
static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) {
lfs2->cfg = cfg;
lfs2->block_count = cfg->block_count; // May be 0
@@ -4126,6 +4214,14 @@ static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) {
// which littlefs currently does not support
LFS2_ASSERT((bool)0x80000000);
+ // check that the required io functions are provided
+ LFS2_ASSERT(lfs2->cfg->read != NULL);
+#ifndef LFS2_READONLY
+ LFS2_ASSERT(lfs2->cfg->prog != NULL);
+ LFS2_ASSERT(lfs2->cfg->erase != NULL);
+ LFS2_ASSERT(lfs2->cfg->sync != NULL);
+#endif
+
// validate that the lfs2-cfg sizes were initiated properly before
// performing any arithmetic logics with them
LFS2_ASSERT(lfs2->cfg->read_size != 0);
@@ -4153,6 +4249,23 @@ static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) {
// wear-leveling.
LFS2_ASSERT(lfs2->cfg->block_cycles != 0);
+ // check that compact_thresh makes sense
+ //
+ // metadata can't be compacted below block_size/2, and metadata can't
+ // exceed a block_size
+ LFS2_ASSERT(lfs2->cfg->compact_thresh == 0
+ || lfs2->cfg->compact_thresh >= lfs2->cfg->block_size/2);
+ LFS2_ASSERT(lfs2->cfg->compact_thresh == (lfs2_size_t)-1
+ || lfs2->cfg->compact_thresh <= lfs2->cfg->block_size);
+
+ // check that metadata_max is a multiple of read_size and prog_size,
+ // and a factor of the block_size
+ LFS2_ASSERT(!lfs2->cfg->metadata_max
+ || lfs2->cfg->metadata_max % lfs2->cfg->read_size == 0);
+ LFS2_ASSERT(!lfs2->cfg->metadata_max
+ || lfs2->cfg->metadata_max % lfs2->cfg->prog_size == 0);
+ LFS2_ASSERT(!lfs2->cfg->metadata_max
+ || lfs2->cfg->block_size % lfs2->cfg->metadata_max == 0);
// setup read cache
if (lfs2->cfg->read_buffer) {
@@ -4180,15 +4293,14 @@ static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) {
lfs2_cache_zero(lfs2, &lfs2->rcache);
lfs2_cache_zero(lfs2, &lfs2->pcache);
- // setup lookahead, must be multiple of 64-bits, 32-bit aligned
+ // setup lookahead buffer, note mount finishes initializing this after
+ // we establish a decent pseudo-random seed
LFS2_ASSERT(lfs2->cfg->lookahead_size > 0);
- LFS2_ASSERT(lfs2->cfg->lookahead_size % 8 == 0 &&
- (uintptr_t)lfs2->cfg->lookahead_buffer % 4 == 0);
if (lfs2->cfg->lookahead_buffer) {
- lfs2->free.buffer = lfs2->cfg->lookahead_buffer;
+ lfs2->lookahead.buffer = lfs2->cfg->lookahead_buffer;
} else {
- lfs2->free.buffer = lfs2_malloc(lfs2->cfg->lookahead_size);
- if (!lfs2->free.buffer) {
+ lfs2->lookahead.buffer = lfs2_malloc(lfs2->cfg->lookahead_size);
+ if (!lfs2->lookahead.buffer) {
err = LFS2_ERR_NOMEM;
goto cleanup;
}
@@ -4215,6 +4327,27 @@ static int lfs2_init(lfs2_t *lfs2, const struct lfs2_config *cfg) {
LFS2_ASSERT(lfs2->cfg->metadata_max <= lfs2->cfg->block_size);
+ LFS2_ASSERT(lfs2->cfg->inline_max == (lfs2_size_t)-1
+ || lfs2->cfg->inline_max <= lfs2->cfg->cache_size);
+ LFS2_ASSERT(lfs2->cfg->inline_max == (lfs2_size_t)-1
+ || lfs2->cfg->inline_max <= lfs2->attr_max);
+ LFS2_ASSERT(lfs2->cfg->inline_max == (lfs2_size_t)-1
+ || lfs2->cfg->inline_max <= ((lfs2->cfg->metadata_max)
+ ? lfs2->cfg->metadata_max
+ : lfs2->cfg->block_size)/8);
+ lfs2->inline_max = lfs2->cfg->inline_max;
+ if (lfs2->inline_max == (lfs2_size_t)-1) {
+ lfs2->inline_max = 0;
+ } else if (lfs2->inline_max == 0) {
+ lfs2->inline_max = lfs2_min(
+ lfs2->cfg->cache_size,
+ lfs2_min(
+ lfs2->attr_max,
+ ((lfs2->cfg->metadata_max)
+ ? lfs2->cfg->metadata_max
+ : lfs2->cfg->block_size)/8));
+ }
+
// setup default state
lfs2->root[0] = LFS2_BLOCK_NULL;
lfs2->root[1] = LFS2_BLOCK_NULL;
@@ -4245,7 +4378,7 @@ static int lfs2_deinit(lfs2_t *lfs2) {
}
if (!lfs2->cfg->lookahead_buffer) {
- lfs2_free(lfs2->free.buffer);
+ lfs2_free(lfs2->lookahead.buffer);
}
return 0;
@@ -4254,7 +4387,7 @@ static int lfs2_deinit(lfs2_t *lfs2) {
#ifndef LFS2_READONLY
-static int lfs2_rawformat(lfs2_t *lfs2, const struct lfs2_config *cfg) {
+static int lfs2_format_(lfs2_t *lfs2, const struct lfs2_config *cfg) {
int err = 0;
{
err = lfs2_init(lfs2, cfg);
@@ -4265,12 +4398,12 @@ static int lfs2_rawformat(lfs2_t *lfs2, const struct lfs2_config *cfg) {
LFS2_ASSERT(cfg->block_count != 0);
// create free lookahead
- memset(lfs2->free.buffer, 0, lfs2->cfg->lookahead_size);
- lfs2->free.off = 0;
- lfs2->free.size = lfs2_min(8*lfs2->cfg->lookahead_size,
+ memset(lfs2->lookahead.buffer, 0, lfs2->cfg->lookahead_size);
+ lfs2->lookahead.start = 0;
+ lfs2->lookahead.size = lfs2_min(8*lfs2->cfg->lookahead_size,
lfs2->block_count);
- lfs2->free.i = 0;
- lfs2_alloc_ack(lfs2);
+ lfs2->lookahead.next = 0;
+ lfs2_alloc_ckpoint(lfs2);
// create root dir
lfs2_mdir_t root;
@@ -4321,7 +4454,31 @@ cleanup:
}
#endif
-static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) {
+struct lfs2_tortoise_t {
+ lfs2_block_t pair[2];
+ lfs2_size_t i;
+ lfs2_size_t period;
+};
+
+static int lfs2_tortoise_detectcycles(
+ const lfs2_mdir_t *dir, struct lfs2_tortoise_t *tortoise) {
+ // detect cycles with Brent's algorithm
+ if (lfs2_pair_issync(dir->tail, tortoise->pair)) {
+ LFS2_WARN("Cycle detected in tail list");
+ return LFS2_ERR_CORRUPT;
+ }
+ if (tortoise->i == tortoise->period) {
+ tortoise->pair[0] = dir->tail[0];
+ tortoise->pair[1] = dir->tail[1];
+ tortoise->i = 0;
+ tortoise->period *= 2;
+ }
+ tortoise->i += 1;
+
+ return LFS2_ERR_OK;
+}
+
+static int lfs2_mount_(lfs2_t *lfs2, const struct lfs2_config *cfg) {
int err = lfs2_init(lfs2, cfg);
if (err) {
return err;
@@ -4329,23 +4486,16 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) {
// scan directory blocks for superblock and any global updates
lfs2_mdir_t dir = {.tail = {0, 1}};
- lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL};
- lfs2_size_t tortoise_i = 1;
- lfs2_size_t tortoise_period = 1;
+ struct lfs2_tortoise_t tortoise = {
+ .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL},
+ .i = 1,
+ .period = 1,
+ };
while (!lfs2_pair_isnull(dir.tail)) {
- // detect cycles with Brent's algorithm
- if (lfs2_pair_issync(dir.tail, tortoise)) {
- LFS2_WARN("Cycle detected in tail list");
- err = LFS2_ERR_CORRUPT;
+ err = lfs2_tortoise_detectcycles(&dir, &tortoise);
+ if (err < 0) {
goto cleanup;
}
- if (tortoise_i == tortoise_period) {
- tortoise[0] = dir.tail[0];
- tortoise[1] = dir.tail[1];
- tortoise_i = 0;
- tortoise_period *= 2;
- }
- tortoise_i += 1;
// fetch next block in tail list
lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, &dir, dir.tail,
@@ -4394,6 +4544,7 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) {
// found older minor version? set an in-device only bit in the
// gstate so we know we need to rewrite the superblock before
// the first write
+ bool needssuperblock = false;
if (minor_version < lfs2_fs_disk_version_minor(lfs2)) {
LFS2_DEBUG("Found older minor version "
"v%"PRIu16".%"PRIu16" < v%"PRIu16".%"PRIu16,
@@ -4401,10 +4552,11 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) {
minor_version,
lfs2_fs_disk_version_major(lfs2),
lfs2_fs_disk_version_minor(lfs2));
- // note this bit is reserved on disk, so fetching more gstate
- // will not interfere here
- lfs2_fs_prepsuperblock(lfs2, true);
+ needssuperblock = true;
}
+ // note this bit is reserved on disk, so fetching more gstate
+ // will not interfere here
+ lfs2_fs_prepsuperblock(lfs2, needssuperblock);
// check superblock configuration
if (superblock.name_max) {
@@ -4438,6 +4590,9 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) {
}
lfs2->attr_max = superblock.attr_max;
+
+ // we also need to update inline_max in case attr_max changed
+ lfs2->inline_max = lfs2_min(lfs2->inline_max, lfs2->attr_max);
}
// this is where we get the block_count from disk if block_count=0
@@ -4478,23 +4633,23 @@ static int lfs2_rawmount(lfs2_t *lfs2, const struct lfs2_config *cfg) {
// setup free lookahead, to distribute allocations uniformly across
// boots, we start the allocator at a random location
- lfs2->free.off = lfs2->seed % lfs2->block_count;
+ lfs2->lookahead.start = lfs2->seed % lfs2->block_count;
lfs2_alloc_drop(lfs2);
return 0;
cleanup:
- lfs2_rawunmount(lfs2);
+ lfs2_unmount_(lfs2);
return err;
}
-static int lfs2_rawunmount(lfs2_t *lfs2) {
+static int lfs2_unmount_(lfs2_t *lfs2) {
return lfs2_deinit(lfs2);
}
/// Filesystem filesystem operations ///
-static int lfs2_fs_rawstat(lfs2_t *lfs2, struct lfs2_fsinfo *fsinfo) {
+static int lfs2_fs_stat_(lfs2_t *lfs2, struct lfs2_fsinfo *fsinfo) {
// if the superblock is up-to-date, we must be on the most recent
// minor version of littlefs
if (!lfs2_gstate_needssuperblock(&lfs2->gstate)) {
@@ -4534,7 +4689,7 @@ static int lfs2_fs_rawstat(lfs2_t *lfs2, struct lfs2_fsinfo *fsinfo) {
return 0;
}
-int lfs2_fs_rawtraverse(lfs2_t *lfs2,
+int lfs2_fs_traverse_(lfs2_t *lfs2,
int (*cb)(void *data, lfs2_block_t block), void *data,
bool includeorphans) {
// iterate over metadata pairs
@@ -4553,22 +4708,17 @@ int lfs2_fs_rawtraverse(lfs2_t *lfs2,
}
#endif
- lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL};
- lfs2_size_t tortoise_i = 1;
- lfs2_size_t tortoise_period = 1;
+ struct lfs2_tortoise_t tortoise = {
+ .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL},
+ .i = 1,
+ .period = 1,
+ };
+ int err = LFS2_ERR_OK;
while (!lfs2_pair_isnull(dir.tail)) {
- // detect cycles with Brent's algorithm
- if (lfs2_pair_issync(dir.tail, tortoise)) {
- LFS2_WARN("Cycle detected in tail list");
+ err = lfs2_tortoise_detectcycles(&dir, &tortoise);
+ if (err < 0) {
return LFS2_ERR_CORRUPT;
}
- if (tortoise_i == tortoise_period) {
- tortoise[0] = dir.tail[0];
- tortoise[1] = dir.tail[1];
- tortoise_i = 0;
- tortoise_period *= 2;
- }
- tortoise_i += 1;
for (int i = 0; i < 2; i++) {
int err = cb(data, dir.tail[i]);
@@ -4647,22 +4797,17 @@ static int lfs2_fs_pred(lfs2_t *lfs2,
// iterate over all directory directory entries
pdir->tail[0] = 0;
pdir->tail[1] = 1;
- lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL};
- lfs2_size_t tortoise_i = 1;
- lfs2_size_t tortoise_period = 1;
+ struct lfs2_tortoise_t tortoise = {
+ .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL},
+ .i = 1,
+ .period = 1,
+ };
+ int err = LFS2_ERR_OK;
while (!lfs2_pair_isnull(pdir->tail)) {
- // detect cycles with Brent's algorithm
- if (lfs2_pair_issync(pdir->tail, tortoise)) {
- LFS2_WARN("Cycle detected in tail list");
+ err = lfs2_tortoise_detectcycles(pdir, &tortoise);
+ if (err < 0) {
return LFS2_ERR_CORRUPT;
}
- if (tortoise_i == tortoise_period) {
- tortoise[0] = pdir->tail[0];
- tortoise[1] = pdir->tail[1];
- tortoise_i = 0;
- tortoise_period *= 2;
- }
- tortoise_i += 1;
if (lfs2_pair_cmp(pdir->tail, pair) == 0) {
return 0;
@@ -4712,22 +4857,17 @@ static lfs2_stag_t lfs2_fs_parent(lfs2_t *lfs2, const lfs2_block_t pair[2],
// use fetchmatch with callback to find pairs
parent->tail[0] = 0;
parent->tail[1] = 1;
- lfs2_block_t tortoise[2] = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL};
- lfs2_size_t tortoise_i = 1;
- lfs2_size_t tortoise_period = 1;
+ struct lfs2_tortoise_t tortoise = {
+ .pair = {LFS2_BLOCK_NULL, LFS2_BLOCK_NULL},
+ .i = 1,
+ .period = 1,
+ };
+ int err = LFS2_ERR_OK;
while (!lfs2_pair_isnull(parent->tail)) {
- // detect cycles with Brent's algorithm
- if (lfs2_pair_issync(parent->tail, tortoise)) {
- LFS2_WARN("Cycle detected in tail list");
- return LFS2_ERR_CORRUPT;
- }
- if (tortoise_i == tortoise_period) {
- tortoise[0] = parent->tail[0];
- tortoise[1] = parent->tail[1];
- tortoise_i = 0;
- tortoise_period *= 2;
+ err = lfs2_tortoise_detectcycles(parent, &tortoise);
+ if (err < 0) {
+ return err;
}
- tortoise_i += 1;
lfs2_stag_t tag = lfs2_dir_fetchmatch(lfs2, parent, parent->tail,
LFS2_MKTAG(0x7ff, 0, 0x3ff),
@@ -4999,7 +5139,7 @@ static int lfs2_fs_forceconsistency(lfs2_t *lfs2) {
#endif
#ifndef LFS2_READONLY
-static int lfs2_fs_rawmkconsistent(lfs2_t *lfs2) {
+static int lfs2_fs_mkconsistent_(lfs2_t *lfs2) {
// lfs2_fs_forceconsistency does most of the work here
int err = lfs2_fs_forceconsistency(lfs2);
if (err) {
@@ -5035,9 +5175,9 @@ static int lfs2_fs_size_count(void *p, lfs2_block_t block) {
return 0;
}
-static lfs2_ssize_t lfs2_fs_rawsize(lfs2_t *lfs2) {
+static lfs2_ssize_t lfs2_fs_size_(lfs2_t *lfs2) {
lfs2_size_t size = 0;
- int err = lfs2_fs_rawtraverse(lfs2, lfs2_fs_size_count, &size, false);
+ int err = lfs2_fs_traverse_(lfs2, lfs2_fs_size_count, &size, false);
if (err) {
return err;
}
@@ -5045,41 +5185,116 @@ static lfs2_ssize_t lfs2_fs_rawsize(lfs2_t *lfs2) {
return size;
}
+// explicit garbage collection
#ifndef LFS2_READONLY
-static int lfs2_fs_rawgrow(lfs2_t *lfs2, lfs2_size_t block_count) {
- // shrinking is not supported
- LFS2_ASSERT(block_count >= lfs2->block_count);
+static int lfs2_fs_gc_(lfs2_t *lfs2) {
+ // 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?
+ int err = lfs2_fs_forceconsistency(lfs2);
+ if (err) {
+ return err;
+ }
- if (block_count > lfs2->block_count) {
- lfs2->block_count = block_count;
+ // try to compact metadata pairs, note we can't really accomplish
+ // anything if compact_thresh doesn't at least leave a prog_size
+ // available
+ if (lfs2->cfg->compact_thresh
+ < lfs2->cfg->block_size - lfs2->cfg->prog_size) {
+ // iterate over all mdirs
+ lfs2_mdir_t mdir = {.tail = {0, 1}};
+ while (!lfs2_pair_isnull(mdir.tail)) {
+ err = lfs2_dir_fetch(lfs2, &mdir, mdir.tail);
+ if (err) {
+ return err;
+ }
- // fetch the root
- lfs2_mdir_t root;
- int err = lfs2_dir_fetch(lfs2, &root, lfs2->root);
+ // not erased? exceeds our compaction threshold?
+ if (!mdir.erased || ((lfs2->cfg->compact_thresh == 0)
+ ? mdir.off > lfs2->cfg->block_size - lfs2->cfg->block_size/8
+ : mdir.off > lfs2->cfg->compact_thresh)) {
+ // the easiest way to trigger a compaction is to mark
+ // the mdir as unerased and add an empty commit
+ mdir.erased = false;
+ err = lfs2_dir_commit(lfs2, &mdir, NULL, 0);
+ if (err) {
+ return err;
+ }
+ }
+ }
+ }
+
+ // try to populate the lookahead buffer, unless it's already full
+ if (lfs2->lookahead.size < 8*lfs2->cfg->lookahead_size) {
+ err = lfs2_alloc_scan(lfs2);
if (err) {
return err;
}
+ }
- // update the superblock
- lfs2_superblock_t superblock;
- lfs2_stag_t tag = lfs2_dir_get(lfs2, &root, LFS2_MKTAG(0x7ff, 0x3ff, 0),
- LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
- &superblock);
- if (tag < 0) {
- return tag;
- }
- lfs2_superblock_fromle32(&superblock);
+ return 0;
+}
+#endif
+
+#ifndef LFS2_READONLY
+#ifdef LFS2_SHRINKNONRELOCATING
+static int lfs2_shrink_checkblock(void *data, lfs2_block_t block) {
+ lfs2_size_t threshold = *((lfs2_size_t*)data);
+ if (block >= threshold) {
+ return LFS2_ERR_NOTEMPTY;
+ }
+ return 0;
+}
+#endif
- superblock.block_count = lfs2->block_count;
+static int lfs2_fs_grow_(lfs2_t *lfs2, lfs2_size_t block_count) {
+ int err;
- lfs2_superblock_tole32(&superblock);
- err = lfs2_dir_commit(lfs2, &root, LFS2_MKATTRS(
- {tag, &superblock}));
+ if (block_count == lfs2->block_count) {
+ return 0;
+ }
+
+
+#ifndef LFS2_SHRINKNONRELOCATING
+ // shrinking is not supported
+ LFS2_ASSERT(block_count >= lfs2->block_count);
+#endif
+#ifdef LFS2_SHRINKNONRELOCATING
+ if (block_count < lfs2->block_count) {
+ err = lfs2_fs_traverse_(lfs2, lfs2_shrink_checkblock, &block_count, true);
if (err) {
return err;
}
}
+#endif
+
+ lfs2->block_count = block_count;
+ // fetch the root
+ lfs2_mdir_t root;
+ err = lfs2_dir_fetch(lfs2, &root, lfs2->root);
+ if (err) {
+ return err;
+ }
+
+ // update the superblock
+ lfs2_superblock_t superblock;
+ lfs2_stag_t tag = lfs2_dir_get(lfs2, &root, LFS2_MKTAG(0x7ff, 0x3ff, 0),
+ LFS2_MKTAG(LFS2_TYPE_INLINESTRUCT, 0, sizeof(superblock)),
+ &superblock);
+ if (tag < 0) {
+ return tag;
+ }
+ lfs2_superblock_fromle32(&superblock);
+
+ superblock.block_count = lfs2->block_count;
+
+ lfs2_superblock_tole32(&superblock);
+ err = lfs2_dir_commit(lfs2, &root, LFS2_MKATTRS(
+ {tag, &superblock}));
+ if (err) {
+ return err;
+ }
return 0;
}
#endif
@@ -5451,10 +5666,10 @@ static int lfs21_mount(lfs2_t *lfs2, struct lfs21 *lfs21,
lfs2->lfs21->root[1] = LFS2_BLOCK_NULL;
// setup free lookahead
- lfs2->free.off = 0;
- lfs2->free.size = 0;
- lfs2->free.i = 0;
- lfs2_alloc_ack(lfs2);
+ lfs2->lookahead.start = 0;
+ lfs2->lookahead.size = 0;
+ lfs2->lookahead.next = 0;
+ lfs2_alloc_ckpoint(lfs2);
// load superblock
lfs21_dir_t dir;
@@ -5505,7 +5720,7 @@ static int lfs21_unmount(lfs2_t *lfs2) {
}
/// v1 migration ///
-static int lfs2_rawmigrate(lfs2_t *lfs2, const struct lfs2_config *cfg) {
+static int lfs2_migrate_(lfs2_t *lfs2, const struct lfs2_config *cfg) {
struct lfs21 lfs21;
// Indeterminate filesystem size not allowed for migration.
@@ -5759,7 +5974,7 @@ int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *cfg) {
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
".read_size=%"PRIu32", .prog_size=%"PRIu32", "
".block_size=%"PRIu32", .block_count=%"PRIu32", "
- ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
+ ".block_cycles=%"PRId32", .cache_size=%"PRIu32", "
".lookahead_size=%"PRIu32", .read_buffer=%p, "
".prog_buffer=%p, .lookahead_buffer=%p, "
".name_max=%"PRIu32", .file_max=%"PRIu32", "
@@ -5772,7 +5987,7 @@ int lfs2_format(lfs2_t *lfs2, const struct lfs2_config *cfg) {
cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
cfg->name_max, cfg->file_max, cfg->attr_max);
- err = lfs2_rawformat(lfs2, cfg);
+ err = lfs2_format_(lfs2, cfg);
LFS2_TRACE("lfs2_format -> %d", err);
LFS2_UNLOCK(cfg);
@@ -5789,7 +6004,7 @@ int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *cfg) {
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
".read_size=%"PRIu32", .prog_size=%"PRIu32", "
".block_size=%"PRIu32", .block_count=%"PRIu32", "
- ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
+ ".block_cycles=%"PRId32", .cache_size=%"PRIu32", "
".lookahead_size=%"PRIu32", .read_buffer=%p, "
".prog_buffer=%p, .lookahead_buffer=%p, "
".name_max=%"PRIu32", .file_max=%"PRIu32", "
@@ -5802,7 +6017,7 @@ int lfs2_mount(lfs2_t *lfs2, const struct lfs2_config *cfg) {
cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
cfg->name_max, cfg->file_max, cfg->attr_max);
- err = lfs2_rawmount(lfs2, cfg);
+ err = lfs2_mount_(lfs2, cfg);
LFS2_TRACE("lfs2_mount -> %d", err);
LFS2_UNLOCK(cfg);
@@ -5816,7 +6031,7 @@ int lfs2_unmount(lfs2_t *lfs2) {
}
LFS2_TRACE("lfs2_unmount(%p)", (void*)lfs2);
- err = lfs2_rawunmount(lfs2);
+ err = lfs2_unmount_(lfs2);
LFS2_TRACE("lfs2_unmount -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -5831,7 +6046,7 @@ int lfs2_remove(lfs2_t *lfs2, const char *path) {
}
LFS2_TRACE("lfs2_remove(%p, \"%s\")", (void*)lfs2, path);
- err = lfs2_rawremove(lfs2, path);
+ err = lfs2_remove_(lfs2, path);
LFS2_TRACE("lfs2_remove -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -5847,7 +6062,7 @@ int lfs2_rename(lfs2_t *lfs2, const char *oldpath, const char *newpath) {
}
LFS2_TRACE("lfs2_rename(%p, \"%s\", \"%s\")", (void*)lfs2, oldpath, newpath);
- err = lfs2_rawrename(lfs2, oldpath, newpath);
+ err = lfs2_rename_(lfs2, oldpath, newpath);
LFS2_TRACE("lfs2_rename -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -5862,7 +6077,7 @@ int lfs2_stat(lfs2_t *lfs2, const char *path, struct lfs2_info *info) {
}
LFS2_TRACE("lfs2_stat(%p, \"%s\", %p)", (void*)lfs2, path, (void*)info);
- err = lfs2_rawstat(lfs2, path, info);
+ err = lfs2_stat_(lfs2, path, info);
LFS2_TRACE("lfs2_stat -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -5878,7 +6093,7 @@ lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path,
LFS2_TRACE("lfs2_getattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")",
(void*)lfs2, path, type, buffer, size);
- lfs2_ssize_t res = lfs2_rawgetattr(lfs2, path, type, buffer, size);
+ lfs2_ssize_t res = lfs2_getattr_(lfs2, path, type, buffer, size);
LFS2_TRACE("lfs2_getattr -> %"PRId32, res);
LFS2_UNLOCK(lfs2->cfg);
@@ -5895,7 +6110,7 @@ int lfs2_setattr(lfs2_t *lfs2, const char *path,
LFS2_TRACE("lfs2_setattr(%p, \"%s\", %"PRIu8", %p, %"PRIu32")",
(void*)lfs2, path, type, buffer, size);
- err = lfs2_rawsetattr(lfs2, path, type, buffer, size);
+ err = lfs2_setattr_(lfs2, path, type, buffer, size);
LFS2_TRACE("lfs2_setattr -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -5911,7 +6126,7 @@ int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type) {
}
LFS2_TRACE("lfs2_removeattr(%p, \"%s\", %"PRIu8")", (void*)lfs2, path, type);
- err = lfs2_rawremoveattr(lfs2, path, type);
+ err = lfs2_removeattr_(lfs2, path, type);
LFS2_TRACE("lfs2_removeattr -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -5926,10 +6141,10 @@ int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file, const char *path, int flags)
return err;
}
LFS2_TRACE("lfs2_file_open(%p, %p, \"%s\", %x)",
- (void*)lfs2, (void*)file, path, flags);
+ (void*)lfs2, (void*)file, path, (unsigned)flags);
LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
- err = lfs2_file_rawopen(lfs2, file, path, flags);
+ err = lfs2_file_open_(lfs2, file, path, flags);
LFS2_TRACE("lfs2_file_open -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -5946,11 +6161,11 @@ int lfs2_file_opencfg(lfs2_t *lfs2, lfs2_file_t *file,
}
LFS2_TRACE("lfs2_file_opencfg(%p, %p, \"%s\", %x, %p {"
".buffer=%p, .attrs=%p, .attr_count=%"PRIu32"})",
- (void*)lfs2, (void*)file, path, flags,
+ (void*)lfs2, (void*)file, path, (unsigned)flags,
(void*)cfg, cfg->buffer, (void*)cfg->attrs, cfg->attr_count);
LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
- err = lfs2_file_rawopencfg(lfs2, file, path, flags, cfg);
+ err = lfs2_file_opencfg_(lfs2, file, path, flags, cfg);
LFS2_TRACE("lfs2_file_opencfg -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -5965,7 +6180,7 @@ int lfs2_file_close(lfs2_t *lfs2, lfs2_file_t *file) {
LFS2_TRACE("lfs2_file_close(%p, %p)", (void*)lfs2, (void*)file);
LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
- err = lfs2_file_rawclose(lfs2, file);
+ err = lfs2_file_close_(lfs2, file);
LFS2_TRACE("lfs2_file_close -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -5981,7 +6196,7 @@ int lfs2_file_sync(lfs2_t *lfs2, lfs2_file_t *file) {
LFS2_TRACE("lfs2_file_sync(%p, %p)", (void*)lfs2, (void*)file);
LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
- err = lfs2_file_rawsync(lfs2, file);
+ err = lfs2_file_sync_(lfs2, file);
LFS2_TRACE("lfs2_file_sync -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -5999,7 +6214,7 @@ lfs2_ssize_t lfs2_file_read(lfs2_t *lfs2, lfs2_file_t *file,
(void*)lfs2, (void*)file, buffer, size);
LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
- lfs2_ssize_t res = lfs2_file_rawread(lfs2, file, buffer, size);
+ lfs2_ssize_t res = lfs2_file_read_(lfs2, file, buffer, size);
LFS2_TRACE("lfs2_file_read -> %"PRId32, res);
LFS2_UNLOCK(lfs2->cfg);
@@ -6017,7 +6232,7 @@ lfs2_ssize_t lfs2_file_write(lfs2_t *lfs2, lfs2_file_t *file,
(void*)lfs2, (void*)file, buffer, size);
LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
- lfs2_ssize_t res = lfs2_file_rawwrite(lfs2, file, buffer, size);
+ lfs2_ssize_t res = lfs2_file_write_(lfs2, file, buffer, size);
LFS2_TRACE("lfs2_file_write -> %"PRId32, res);
LFS2_UNLOCK(lfs2->cfg);
@@ -6035,7 +6250,7 @@ lfs2_soff_t lfs2_file_seek(lfs2_t *lfs2, lfs2_file_t *file,
(void*)lfs2, (void*)file, off, whence);
LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
- lfs2_soff_t res = lfs2_file_rawseek(lfs2, file, off, whence);
+ lfs2_soff_t res = lfs2_file_seek_(lfs2, file, off, whence);
LFS2_TRACE("lfs2_file_seek -> %"PRId32, res);
LFS2_UNLOCK(lfs2->cfg);
@@ -6052,7 +6267,7 @@ int lfs2_file_truncate(lfs2_t *lfs2, lfs2_file_t *file, lfs2_off_t size) {
(void*)lfs2, (void*)file, size);
LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
- err = lfs2_file_rawtruncate(lfs2, file, size);
+ err = lfs2_file_truncate_(lfs2, file, size);
LFS2_TRACE("lfs2_file_truncate -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -6068,7 +6283,7 @@ lfs2_soff_t lfs2_file_tell(lfs2_t *lfs2, lfs2_file_t *file) {
LFS2_TRACE("lfs2_file_tell(%p, %p)", (void*)lfs2, (void*)file);
LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
- lfs2_soff_t res = lfs2_file_rawtell(lfs2, file);
+ lfs2_soff_t res = lfs2_file_tell_(lfs2, file);
LFS2_TRACE("lfs2_file_tell -> %"PRId32, res);
LFS2_UNLOCK(lfs2->cfg);
@@ -6082,7 +6297,7 @@ int lfs2_file_rewind(lfs2_t *lfs2, lfs2_file_t *file) {
}
LFS2_TRACE("lfs2_file_rewind(%p, %p)", (void*)lfs2, (void*)file);
- err = lfs2_file_rawrewind(lfs2, file);
+ err = lfs2_file_rewind_(lfs2, file);
LFS2_TRACE("lfs2_file_rewind -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -6097,9 +6312,9 @@ lfs2_soff_t lfs2_file_size(lfs2_t *lfs2, lfs2_file_t *file) {
LFS2_TRACE("lfs2_file_size(%p, %p)", (void*)lfs2, (void*)file);
LFS2_ASSERT(lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)file));
- lfs2_soff_t res = lfs2_file_rawsize(lfs2, file);
+ lfs2_soff_t res = lfs2_file_size_(lfs2, file);
- LFS2_TRACE("lfs2_file_size -> %"PRId32, res);
+ LFS2_TRACE("lfs2_file_size -> %"PRIu32, res);
LFS2_UNLOCK(lfs2->cfg);
return res;
}
@@ -6112,7 +6327,7 @@ int lfs2_mkdir(lfs2_t *lfs2, const char *path) {
}
LFS2_TRACE("lfs2_mkdir(%p, \"%s\")", (void*)lfs2, path);
- err = lfs2_rawmkdir(lfs2, path);
+ err = lfs2_mkdir_(lfs2, path);
LFS2_TRACE("lfs2_mkdir -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -6128,7 +6343,7 @@ int lfs2_dir_open(lfs2_t *lfs2, lfs2_dir_t *dir, const char *path) {
LFS2_TRACE("lfs2_dir_open(%p, %p, \"%s\")", (void*)lfs2, (void*)dir, path);
LFS2_ASSERT(!lfs2_mlist_isopen(lfs2->mlist, (struct lfs2_mlist*)dir));
- err = lfs2_dir_rawopen(lfs2, dir, path);
+ err = lfs2_dir_open_(lfs2, dir, path);
LFS2_TRACE("lfs2_dir_open -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -6142,7 +6357,7 @@ int lfs2_dir_close(lfs2_t *lfs2, lfs2_dir_t *dir) {
}
LFS2_TRACE("lfs2_dir_close(%p, %p)", (void*)lfs2, (void*)dir);
- err = lfs2_dir_rawclose(lfs2, dir);
+ err = lfs2_dir_close_(lfs2, dir);
LFS2_TRACE("lfs2_dir_close -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -6157,7 +6372,7 @@ int lfs2_dir_read(lfs2_t *lfs2, lfs2_dir_t *dir, struct lfs2_info *info) {
LFS2_TRACE("lfs2_dir_read(%p, %p, %p)",
(void*)lfs2, (void*)dir, (void*)info);
- err = lfs2_dir_rawread(lfs2, dir, info);
+ err = lfs2_dir_read_(lfs2, dir, info);
LFS2_TRACE("lfs2_dir_read -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -6172,7 +6387,7 @@ int lfs2_dir_seek(lfs2_t *lfs2, lfs2_dir_t *dir, lfs2_off_t off) {
LFS2_TRACE("lfs2_dir_seek(%p, %p, %"PRIu32")",
(void*)lfs2, (void*)dir, off);
- err = lfs2_dir_rawseek(lfs2, dir, off);
+ err = lfs2_dir_seek_(lfs2, dir, off);
LFS2_TRACE("lfs2_dir_seek -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -6186,7 +6401,7 @@ lfs2_soff_t lfs2_dir_tell(lfs2_t *lfs2, lfs2_dir_t *dir) {
}
LFS2_TRACE("lfs2_dir_tell(%p, %p)", (void*)lfs2, (void*)dir);
- lfs2_soff_t res = lfs2_dir_rawtell(lfs2, dir);
+ lfs2_soff_t res = lfs2_dir_tell_(lfs2, dir);
LFS2_TRACE("lfs2_dir_tell -> %"PRId32, res);
LFS2_UNLOCK(lfs2->cfg);
@@ -6200,7 +6415,7 @@ int lfs2_dir_rewind(lfs2_t *lfs2, lfs2_dir_t *dir) {
}
LFS2_TRACE("lfs2_dir_rewind(%p, %p)", (void*)lfs2, (void*)dir);
- err = lfs2_dir_rawrewind(lfs2, dir);
+ err = lfs2_dir_rewind_(lfs2, dir);
LFS2_TRACE("lfs2_dir_rewind -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -6214,7 +6429,7 @@ int lfs2_fs_stat(lfs2_t *lfs2, struct lfs2_fsinfo *fsinfo) {
}
LFS2_TRACE("lfs2_fs_stat(%p, %p)", (void*)lfs2, (void*)fsinfo);
- err = lfs2_fs_rawstat(lfs2, fsinfo);
+ err = lfs2_fs_stat_(lfs2, fsinfo);
LFS2_TRACE("lfs2_fs_stat -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -6228,7 +6443,7 @@ lfs2_ssize_t lfs2_fs_size(lfs2_t *lfs2) {
}
LFS2_TRACE("lfs2_fs_size(%p)", (void*)lfs2);
- lfs2_ssize_t res = lfs2_fs_rawsize(lfs2);
+ lfs2_ssize_t res = lfs2_fs_size_(lfs2);
LFS2_TRACE("lfs2_fs_size -> %"PRId32, res);
LFS2_UNLOCK(lfs2->cfg);
@@ -6243,7 +6458,7 @@ int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void *, lfs2_block_t), void *data)
LFS2_TRACE("lfs2_fs_traverse(%p, %p, %p)",
(void*)lfs2, (void*)(uintptr_t)cb, data);
- err = lfs2_fs_rawtraverse(lfs2, cb, data, true);
+ err = lfs2_fs_traverse_(lfs2, cb, data, true);
LFS2_TRACE("lfs2_fs_traverse -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -6251,32 +6466,32 @@ int lfs2_fs_traverse(lfs2_t *lfs2, int (*cb)(void *, lfs2_block_t), void *data)
}
#ifndef LFS2_READONLY
-int lfs2_fs_gc(lfs2_t *lfs2) {
+int lfs2_fs_mkconsistent(lfs2_t *lfs2) {
int err = LFS2_LOCK(lfs2->cfg);
if (err) {
return err;
}
- LFS2_TRACE("lfs2_fs_gc(%p)", (void*)lfs2);
+ LFS2_TRACE("lfs2_fs_mkconsistent(%p)", (void*)lfs2);
- err = lfs2_fs_rawgc(lfs2);
+ err = lfs2_fs_mkconsistent_(lfs2);
- LFS2_TRACE("lfs2_fs_gc -> %d", err);
+ LFS2_TRACE("lfs2_fs_mkconsistent -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
return err;
}
#endif
#ifndef LFS2_READONLY
-int lfs2_fs_mkconsistent(lfs2_t *lfs2) {
+int lfs2_fs_gc(lfs2_t *lfs2) {
int err = LFS2_LOCK(lfs2->cfg);
if (err) {
return err;
}
- LFS2_TRACE("lfs2_fs_mkconsistent(%p)", (void*)lfs2);
+ LFS2_TRACE("lfs2_fs_gc(%p)", (void*)lfs2);
- err = lfs2_fs_rawmkconsistent(lfs2);
+ err = lfs2_fs_gc_(lfs2);
- LFS2_TRACE("lfs2_fs_mkconsistent -> %d", err);
+ LFS2_TRACE("lfs2_fs_gc -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
return err;
}
@@ -6290,7 +6505,7 @@ int lfs2_fs_grow(lfs2_t *lfs2, lfs2_size_t block_count) {
}
LFS2_TRACE("lfs2_fs_grow(%p, %"PRIu32")", (void*)lfs2, block_count);
- err = lfs2_fs_rawgrow(lfs2, block_count);
+ err = lfs2_fs_grow_(lfs2, block_count);
LFS2_TRACE("lfs2_fs_grow -> %d", err);
LFS2_UNLOCK(lfs2->cfg);
@@ -6308,7 +6523,7 @@ int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg) {
".read=%p, .prog=%p, .erase=%p, .sync=%p, "
".read_size=%"PRIu32", .prog_size=%"PRIu32", "
".block_size=%"PRIu32", .block_count=%"PRIu32", "
- ".block_cycles=%"PRIu32", .cache_size=%"PRIu32", "
+ ".block_cycles=%"PRId32", .cache_size=%"PRIu32", "
".lookahead_size=%"PRIu32", .read_buffer=%p, "
".prog_buffer=%p, .lookahead_buffer=%p, "
".name_max=%"PRIu32", .file_max=%"PRIu32", "
@@ -6321,7 +6536,7 @@ int lfs2_migrate(lfs2_t *lfs2, const struct lfs2_config *cfg) {
cfg->read_buffer, cfg->prog_buffer, cfg->lookahead_buffer,
cfg->name_max, cfg->file_max, cfg->attr_max);
- err = lfs2_rawmigrate(lfs2, cfg);
+ err = lfs2_migrate_(lfs2, cfg);
LFS2_TRACE("lfs2_migrate -> %d", err);
LFS2_UNLOCK(cfg);