forked from Imagelibrary/littlefs
Compare commits
8 Commits
ci-ubuntu-
...
fix-name-o
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52df70c669 | ||
|
|
3513ff1afc | ||
|
|
8a22bd6e67 | ||
|
|
9b82db72d8 | ||
|
|
99b84ee3db | ||
|
|
e91a29d2b5 | ||
|
|
b9b95ab4bc | ||
|
|
10bcff1af8 |
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -112,7 +112,7 @@ jobs:
|
|||||||
table[$i,$j]=$c_camel
|
table[$i,$j]=$c_camel
|
||||||
((j+=1))
|
((j+=1))
|
||||||
|
|
||||||
for s in code stack struct
|
for s in code stack structs
|
||||||
do
|
do
|
||||||
f=sizes/thumb${c:+-$c}.$s.csv
|
f=sizes/thumb${c:+-$c}.$s.csv
|
||||||
[ -e $f ] && table[$i,$j]=$( \
|
[ -e $f ] && table[$i,$j]=$( \
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ This leaves us with three major requirements for an embedded filesystem.
|
|||||||
RAM to temporarily store filesystem metadata.
|
RAM to temporarily store filesystem metadata.
|
||||||
|
|
||||||
For ROM, this means we need to keep our design simple and reuse code paths
|
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
|
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
|
size or number of files. This creates a unique challenge as even presumably
|
||||||
simple operations, such as traversing the filesystem, become surprisingly
|
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.
|
skip-list.
|
||||||
|
|
||||||
The name comes from heavy use of the [CTZ instruction][wikipedia-ctz], which
|
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.
|
that block contains ctz(_n_)+1 pointers.
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
12
lfs.c
12
lfs.c
@@ -1430,8 +1430,8 @@ static int lfs_dir_find_match(void *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// only equal if our size is still the same
|
// only equal if our size is still the same
|
||||||
if (name->size != lfs_tag_size(tag)) {
|
if (lfs_tag_size(tag) != name->size) {
|
||||||
return (name->size < lfs_tag_size(tag)) ? LFS_CMP_LT : LFS_CMP_GT;
|
return (lfs_tag_size(tag) < name->size) ? LFS_CMP_LT : LFS_CMP_GT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// found a match!
|
// found a match!
|
||||||
@@ -2151,9 +2151,11 @@ static int lfs_dir_splittingcompact(lfs_t *lfs, lfs_mdir_t *dir,
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
// do we have extra space? littlefs can't reclaim this space
|
// littlefs cannot reclaim expanded superblocks, so expand cautiously
|
||||||
// by itself, so expand cautiously
|
//
|
||||||
if ((lfs_size_t)size < lfs->block_count/2) {
|
// 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);
|
LFS_DEBUG("Expanding superblock at rev %"PRIu32, dir->rev);
|
||||||
int err = lfs_dir_split(lfs, dir, attrs, attrcount,
|
int err = lfs_dir_split(lfs, dir, attrs, attrcount,
|
||||||
source, begin, end);
|
source, begin, end);
|
||||||
|
|||||||
@@ -717,6 +717,105 @@ code = '''
|
|||||||
lfs_unmount(&lfs) => 0;
|
lfs_unmount(&lfs) => 0;
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
# littlefs should keep directories in lexicographic order
|
||||||
|
[cases.test_dirs_ordering]
|
||||||
|
# ORDER=0 => inorder
|
||||||
|
# ORDER=1 => reversed
|
||||||
|
# ORDER=2 => random
|
||||||
|
defines.ORDER = [0, 1, 2]
|
||||||
|
code = '''
|
||||||
|
lfs_t lfs;
|
||||||
|
lfs_format(&lfs, cfg) => 0;
|
||||||
|
lfs_mount(&lfs, cfg) => 0;
|
||||||
|
if (ORDER == 0) {
|
||||||
|
lfs_mkdir(&lfs, "a") => 0;
|
||||||
|
lfs_mkdir(&lfs, "b") => 0;
|
||||||
|
lfs_mkdir(&lfs, "c") => 0;
|
||||||
|
} else if (ORDER == 1) {
|
||||||
|
lfs_mkdir(&lfs, "c") => 0;
|
||||||
|
lfs_mkdir(&lfs, "b") => 0;
|
||||||
|
lfs_mkdir(&lfs, "a") => 0;
|
||||||
|
} else if (ORDER == 2) {
|
||||||
|
// "random"
|
||||||
|
lfs_mkdir(&lfs, "a") => 0;
|
||||||
|
lfs_mkdir(&lfs, "c") => 0;
|
||||||
|
lfs_mkdir(&lfs, "b") => 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the order
|
||||||
|
lfs_dir_t dir;
|
||||||
|
lfs_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
struct lfs_info info;
|
||||||
|
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, "a") == 0);
|
||||||
|
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, "b") == 0);
|
||||||
|
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, "c") == 0);
|
||||||
|
lfs_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
lfs_dir_close(&lfs, &dir) => 0;
|
||||||
|
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
'''
|
||||||
|
|
||||||
|
[cases.test_dirs_ordering_length]
|
||||||
|
# ORDER=0 => inorder
|
||||||
|
# ORDER=1 => reversed
|
||||||
|
# ORDER=2 => random
|
||||||
|
defines.ORDER = [0, 1, 2]
|
||||||
|
code = '''
|
||||||
|
lfs_t lfs;
|
||||||
|
lfs_format(&lfs, cfg) => 0;
|
||||||
|
lfs_mount(&lfs, cfg) => 0;
|
||||||
|
if (ORDER == 0) {
|
||||||
|
lfs_mkdir(&lfs, "a") => 0;
|
||||||
|
lfs_mkdir(&lfs, "aa") => 0;
|
||||||
|
lfs_mkdir(&lfs, "aaa") => 0;
|
||||||
|
} else if (ORDER == 1) {
|
||||||
|
lfs_mkdir(&lfs, "aaa") => 0;
|
||||||
|
lfs_mkdir(&lfs, "aa") => 0;
|
||||||
|
lfs_mkdir(&lfs, "a") => 0;
|
||||||
|
} else if (ORDER == 2) {
|
||||||
|
// "random"
|
||||||
|
lfs_mkdir(&lfs, "a") => 0;
|
||||||
|
lfs_mkdir(&lfs, "aaa") => 0;
|
||||||
|
lfs_mkdir(&lfs, "aa") => 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check the order
|
||||||
|
lfs_dir_t dir;
|
||||||
|
lfs_dir_open(&lfs, &dir, "/") => 0;
|
||||||
|
struct lfs_info info;
|
||||||
|
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, ".") == 0);
|
||||||
|
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, "..") == 0);
|
||||||
|
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, "a") == 0);
|
||||||
|
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, "aa") == 0);
|
||||||
|
lfs_dir_read(&lfs, &dir, &info) => 1;
|
||||||
|
assert(info.type == LFS_TYPE_DIR);
|
||||||
|
assert(strcmp(info.name, "aaa") == 0);
|
||||||
|
lfs_dir_read(&lfs, &dir, &info) => 0;
|
||||||
|
lfs_dir_close(&lfs, &dir) => 0;
|
||||||
|
|
||||||
|
lfs_unmount(&lfs) => 0;
|
||||||
|
'''
|
||||||
|
|
||||||
[cases.test_dirs_other_errors]
|
[cases.test_dirs_other_errors]
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
|
|||||||
Reference in New Issue
Block a user