mirror of https://github.com/ARMmbed/mbed-os.git
Updated littlefs to '76d00eb38cddfcc267f323c470142b9f4588d3ff'
commit
2e9f87d435
|
@ -1,4 +1,14 @@
|
||||||
script:
|
script:
|
||||||
|
# make sure example can at least compile
|
||||||
|
- sed -n '/``` c/,/```/{/```/d; p;}' README.md > test.c &&
|
||||||
|
CFLAGS='
|
||||||
|
-Duser_provided_block_device_read=NULL
|
||||||
|
-Duser_provided_block_device_prog=NULL
|
||||||
|
-Duser_provided_block_device_erase=NULL
|
||||||
|
-Duser_provided_block_device_sync=NULL
|
||||||
|
-include stdio.h -Werror' make all size
|
||||||
|
|
||||||
|
# run tests
|
||||||
- CFLAGS="-DLFS_READ_SIZE=16 -DLFS_PROG_SIZE=16" make test
|
- CFLAGS="-DLFS_READ_SIZE=16 -DLFS_PROG_SIZE=16" make test
|
||||||
- CFLAGS="-DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" make test
|
- CFLAGS="-DLFS_READ_SIZE=1 -DLFS_PROG_SIZE=1" make test
|
||||||
- CFLAGS="-DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512" make test
|
- CFLAGS="-DLFS_READ_SIZE=512 -DLFS_PROG_SIZE=512" make test
|
||||||
|
|
|
@ -639,9 +639,9 @@ v
|
||||||
'--------' '--------'
|
'--------' '--------'
|
||||||
```
|
```
|
||||||
|
|
||||||
Wait, wait, wait, wait, wait, that's not atomic at all! If power is lost after
|
Wait, wait, wait, that's not atomic at all! If power is lost after removing
|
||||||
removing directory B from the root, directory B is still in the linked-list.
|
directory B from the root, directory B is still in the linked-list. We've
|
||||||
We've just created a memory leak!
|
just created a memory leak!
|
||||||
|
|
||||||
And to be honest, I don't have a clever solution for this case. As a
|
And to be honest, I don't have a clever solution for this case. As a
|
||||||
side-effect of using multiple pointers in the threaded tree, the littlefs
|
side-effect of using multiple pointers in the threaded tree, the littlefs
|
||||||
|
@ -969,5 +969,5 @@ So, to summarize:
|
||||||
10. Any case where an atomic operation is not possible, it is taken care of
|
10. Any case where an atomic operation is not possible, it is taken care of
|
||||||
by a deorphan step that occurs on the first allocation after boot
|
by a deorphan step that occurs on the first allocation after boot
|
||||||
|
|
||||||
Welp, that's the little filesystem. Thanks for reading!
|
That's the little filesystem. Thanks for reading!
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,6 @@ int main(void) {
|
||||||
|
|
||||||
// update boot count
|
// update boot count
|
||||||
boot_count += 1;
|
boot_count += 1;
|
||||||
printf("boot_count: %ld\n", boot_count);
|
|
||||||
lfs_file_rewind(&lfs, &file);
|
lfs_file_rewind(&lfs, &file);
|
||||||
lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));
|
lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));
|
||||||
|
|
||||||
|
@ -86,6 +85,9 @@ int main(void) {
|
||||||
|
|
||||||
// release any resources we were using
|
// release any resources we were using
|
||||||
lfs_unmount(&lfs);
|
lfs_unmount(&lfs);
|
||||||
|
|
||||||
|
// print the boot count
|
||||||
|
printf("boot_count: %d\n", boot_count);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -560,8 +560,7 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir,
|
||||||
const lfs_entry_t *entry, const void *data) {
|
const lfs_entry_t *entry, const void *data) {
|
||||||
return lfs_dir_commit(lfs, dir, (struct lfs_region[]){
|
return lfs_dir_commit(lfs, dir, (struct lfs_region[]){
|
||||||
{entry->off, sizeof(entry->d), &entry->d, sizeof(entry->d)},
|
{entry->off, sizeof(entry->d), &entry->d, sizeof(entry->d)},
|
||||||
{entry->off+sizeof(entry->d), entry->d.len-sizeof(entry->d),
|
{entry->off+sizeof(entry->d), entry->d.nlen, data, entry->d.nlen}
|
||||||
data, entry->d.len-sizeof(entry->d)}
|
|
||||||
}, data ? 2 : 1);
|
}, data ? 2 : 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -569,11 +568,12 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
|
||||||
lfs_entry_t *entry, const void *data) {
|
lfs_entry_t *entry, const void *data) {
|
||||||
// check if we fit, if top bit is set we do not and move on
|
// check if we fit, if top bit is set we do not and move on
|
||||||
while (true) {
|
while (true) {
|
||||||
if (dir->d.size + entry->d.len <= lfs->cfg->block_size) {
|
if (dir->d.size + 4+entry->d.elen+entry->d.alen+entry->d.nlen
|
||||||
|
<= lfs->cfg->block_size) {
|
||||||
entry->off = dir->d.size - 4;
|
entry->off = dir->d.size - 4;
|
||||||
return lfs_dir_commit(lfs, dir, (struct lfs_region[]){
|
return lfs_dir_commit(lfs, dir, (struct lfs_region[]){
|
||||||
{entry->off, 0, &entry->d, sizeof(entry->d)},
|
{entry->off, 0, &entry->d, sizeof(entry->d)},
|
||||||
{entry->off, 0, data, entry->d.len - sizeof(entry->d)}
|
{entry->off, 0, data, entry->d.nlen}
|
||||||
}, 2);
|
}, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,7 +590,7 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir,
|
||||||
entry->off = newdir.d.size - 4;
|
entry->off = newdir.d.size - 4;
|
||||||
err = lfs_dir_commit(lfs, &newdir, (struct lfs_region[]){
|
err = lfs_dir_commit(lfs, &newdir, (struct lfs_region[]){
|
||||||
{entry->off, 0, &entry->d, sizeof(entry->d)},
|
{entry->off, 0, &entry->d, sizeof(entry->d)},
|
||||||
{entry->off, 0, data, entry->d.len - sizeof(entry->d)}
|
{entry->off, 0, data, entry->d.nlen}
|
||||||
}, 2);
|
}, 2);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
|
@ -620,7 +620,8 @@ static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
|
||||||
|
|
||||||
if (!(pdir.d.size & 0x80000000)) {
|
if (!(pdir.d.size & 0x80000000)) {
|
||||||
return lfs_dir_commit(lfs, dir, (struct lfs_region[]){
|
return lfs_dir_commit(lfs, dir, (struct lfs_region[]){
|
||||||
{entry->off, entry->d.len, NULL, 0},
|
{entry->off, 4+entry->d.elen+entry->d.alen+entry->d.nlen,
|
||||||
|
NULL, 0},
|
||||||
}, 1);
|
}, 1);
|
||||||
} else {
|
} else {
|
||||||
pdir.d.tail[0] = dir->d.tail[0];
|
pdir.d.tail[0] = dir->d.tail[0];
|
||||||
|
@ -629,7 +630,8 @@ static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return lfs_dir_commit(lfs, dir, (struct lfs_region[]){
|
return lfs_dir_commit(lfs, dir, (struct lfs_region[]){
|
||||||
{entry->off, entry->d.len, NULL, 0},
|
{entry->off, 4+entry->d.elen+entry->d.alen+entry->d.nlen,
|
||||||
|
NULL, 0},
|
||||||
}, 1);
|
}, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -656,9 +658,9 @@ static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir->off += entry->d.len;
|
entry->off = dir->off;
|
||||||
dir->pos += entry->d.len;
|
dir->off += 4+entry->d.elen+entry->d.alen+entry->d.nlen;
|
||||||
entry->off = dir->off - entry->d.len;
|
dir->pos += 4+entry->d.elen+entry->d.alen+entry->d.nlen;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,12 +715,13 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir,
|
||||||
|
|
||||||
if ((entry->d.type != LFS_TYPE_REG &&
|
if ((entry->d.type != LFS_TYPE_REG &&
|
||||||
entry->d.type != LFS_TYPE_DIR) ||
|
entry->d.type != LFS_TYPE_DIR) ||
|
||||||
entry->d.name != pathlen) {
|
entry->d.nlen != pathlen) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = lfs_bd_cmp(lfs, dir->pair[0],
|
int res = lfs_bd_cmp(lfs, dir->pair[0],
|
||||||
entry->off + sizeof(entry->d), pathname, pathlen);
|
entry->off + 4+entry->d.elen+entry->d.alen,
|
||||||
|
pathname, pathlen);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -784,8 +787,9 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
entry.d.type = LFS_TYPE_DIR;
|
entry.d.type = LFS_TYPE_DIR;
|
||||||
entry.d.name = strlen(path);
|
entry.d.elen = sizeof(entry.d) - 4;
|
||||||
entry.d.len = sizeof(entry.d) + entry.d.name;
|
entry.d.alen = 0;
|
||||||
|
entry.d.nlen = strlen(path);
|
||||||
entry.d.u.dir[0] = dir.pair[0];
|
entry.d.u.dir[0] = dir.pair[0];
|
||||||
entry.d.u.dir[1] = dir.pair[1];
|
entry.d.u.dir[1] = dir.pair[1];
|
||||||
|
|
||||||
|
@ -880,8 +884,9 @@ int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) {
|
||||||
info->size = entry.d.u.file.size;
|
info->size = entry.d.u.file.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int err = lfs_bd_read(lfs, dir->pair[0], entry.off + sizeof(entry.d),
|
int err = lfs_bd_read(lfs, dir->pair[0],
|
||||||
info->name, entry.d.name);
|
entry.off + 4+entry.d.elen+entry.d.alen,
|
||||||
|
info->name, entry.d.nlen);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1117,8 +1122,9 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
|
||||||
|
|
||||||
// create entry to remember name
|
// create entry to remember name
|
||||||
entry.d.type = LFS_TYPE_REG;
|
entry.d.type = LFS_TYPE_REG;
|
||||||
entry.d.name = strlen(path);
|
entry.d.elen = sizeof(entry.d) - 4;
|
||||||
entry.d.len = sizeof(entry.d) + entry.d.name;
|
entry.d.alen = 0;
|
||||||
|
entry.d.nlen = strlen(path);
|
||||||
entry.d.u.file.head = -1;
|
entry.d.u.file.head = -1;
|
||||||
entry.d.u.file.size = 0;
|
entry.d.u.file.size = 0;
|
||||||
err = lfs_dir_append(lfs, &cwd, &entry, path);
|
err = lfs_dir_append(lfs, &cwd, &entry, path);
|
||||||
|
@ -1537,8 +1543,9 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) {
|
||||||
info->size = entry.d.u.file.size;
|
info->size = entry.d.u.file.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = lfs_bd_read(lfs, cwd.pair[0], entry.off + sizeof(entry.d),
|
err = lfs_bd_read(lfs, cwd.pair[0],
|
||||||
info->name, entry.d.name);
|
entry.off + 4+entry.d.elen+entry.d.alen,
|
||||||
|
info->name, entry.d.nlen);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1585,7 +1592,7 @@ int lfs_remove(lfs_t *lfs, const char *path) {
|
||||||
f->pair[0] = 0xffffffff;
|
f->pair[0] = 0xffffffff;
|
||||||
f->pair[1] = 0xffffffff;
|
f->pair[1] = 0xffffffff;
|
||||||
} else if (f->poff > entry.off) {
|
} else if (f->poff > entry.off) {
|
||||||
f->poff -= entry.d.len;
|
f->poff -= 4 + entry.d.elen + entry.d.alen + entry.d.nlen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1651,8 +1658,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
||||||
// move to new location
|
// move to new location
|
||||||
lfs_entry_t newentry = preventry;
|
lfs_entry_t newentry = preventry;
|
||||||
newentry.d = oldentry.d;
|
newentry.d = oldentry.d;
|
||||||
newentry.d.name = strlen(newpath);
|
newentry.d.nlen = strlen(newpath);
|
||||||
newentry.d.len = sizeof(newentry.d) + newentry.d.name;
|
|
||||||
|
|
||||||
if (prevexists) {
|
if (prevexists) {
|
||||||
int err = lfs_dir_update(lfs, &newcwd, &newentry, newpath);
|
int err = lfs_dir_update(lfs, &newcwd, &newentry, newpath);
|
||||||
|
@ -1690,7 +1696,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
|
||||||
f->pair[0] = 0xffffffff;
|
f->pair[0] = 0xffffffff;
|
||||||
f->pair[1] = 0xffffffff;
|
f->pair[1] = 0xffffffff;
|
||||||
} else if (f->poff > oldentry.off) {
|
} else if (f->poff > oldentry.off) {
|
||||||
f->poff -= oldentry.d.len;
|
f->poff -= 4+oldentry.d.elen+oldentry.d.alen+oldentry.d.nlen;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1809,8 +1815,8 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||||
lfs_superblock_t superblock = {
|
lfs_superblock_t superblock = {
|
||||||
.off = sizeof(superdir.d),
|
.off = sizeof(superdir.d),
|
||||||
.d.type = LFS_TYPE_SUPERBLOCK,
|
.d.type = LFS_TYPE_SUPERBLOCK,
|
||||||
.d.name = sizeof(superblock.d.magic),
|
.d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4,
|
||||||
.d.len = sizeof(superblock.d),
|
.d.nlen = sizeof(superblock.d.magic),
|
||||||
.d.version = 0x00010001,
|
.d.version = 0x00010001,
|
||||||
.d.magic = {"littlefs"},
|
.d.magic = {"littlefs"},
|
||||||
.d.block_size = lfs->cfg->block_size,
|
.d.block_size = lfs->cfg->block_size,
|
||||||
|
@ -1865,8 +1871,8 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
|
||||||
lfs_superblock_t superblock;
|
lfs_superblock_t superblock;
|
||||||
err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1});
|
err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1});
|
||||||
if (!err) {
|
if (!err) {
|
||||||
err = lfs_bd_read(lfs, dir.pair[0],
|
err = lfs_bd_read(lfs, dir.pair[0], sizeof(dir.d),
|
||||||
sizeof(dir.d), &superblock.d, sizeof(superblock.d));
|
&superblock.d, sizeof(superblock.d));
|
||||||
|
|
||||||
lfs->root[0] = superblock.d.root[0];
|
lfs->root[0] = superblock.d.root[0];
|
||||||
lfs->root[1] = superblock.d.root[1];
|
lfs->root[1] = superblock.d.root[1];
|
||||||
|
@ -1925,7 +1931,7 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
dir.off += entry.d.len;
|
dir.off += 4+entry.d.elen+entry.d.alen+entry.d.nlen;
|
||||||
if ((0xf & entry.d.type) == (0xf & LFS_TYPE_REG)) {
|
if ((0xf & entry.d.type) == (0xf & LFS_TYPE_REG)) {
|
||||||
int err = lfs_index_traverse(lfs, &lfs->rcache, NULL,
|
int err = lfs_index_traverse(lfs, &lfs->rcache, NULL,
|
||||||
entry.d.u.file.head, entry.d.u.file.size, cb, data);
|
entry.d.u.file.head, entry.d.u.file.size, cb, data);
|
||||||
|
|
|
@ -160,8 +160,9 @@ typedef struct lfs_entry {
|
||||||
|
|
||||||
struct lfs_disk_entry {
|
struct lfs_disk_entry {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t name;
|
uint8_t elen;
|
||||||
uint16_t len;
|
uint8_t alen;
|
||||||
|
uint8_t nlen;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
lfs_block_t head;
|
lfs_block_t head;
|
||||||
|
@ -212,8 +213,9 @@ typedef struct lfs_superblock {
|
||||||
|
|
||||||
struct lfs_disk_superblock {
|
struct lfs_disk_superblock {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t name;
|
uint8_t elen;
|
||||||
uint16_t len;
|
uint8_t alen;
|
||||||
|
uint8_t nlen;
|
||||||
lfs_block_t root[2];
|
lfs_block_t root[2];
|
||||||
uint32_t block_size;
|
uint32_t block_size;
|
||||||
uint32_t block_count;
|
uint32_t block_count;
|
||||||
|
|
Loading…
Reference in New Issue