mirror of
https://github.com/eledio-devices/thirdparty-littlefs.git
synced 2025-11-01 00:38:29 +01:00
WIP simplified and aligned globals
by storing deorphaned in the globals tag itself
This commit is contained in:
165
lfs.c
165
lfs.c
@@ -265,7 +265,6 @@ static int32_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t dir[2],
|
|||||||
lfs_mdir_t *parent);
|
lfs_mdir_t *parent);
|
||||||
static int lfs_fs_relocate(lfs_t *lfs,
|
static int lfs_fs_relocate(lfs_t *lfs,
|
||||||
const lfs_block_t oldpair[2], lfs_block_t newpair[2]);
|
const lfs_block_t oldpair[2], lfs_block_t newpair[2]);
|
||||||
static int lfs_fs_scan(lfs_t *lfs);
|
|
||||||
static int lfs_fs_forceconsistency(lfs_t *lfs);
|
static int lfs_fs_forceconsistency(lfs_t *lfs);
|
||||||
|
|
||||||
|
|
||||||
@@ -410,14 +409,14 @@ static inline lfs_size_t lfs_tagsize(uint32_t tag) {
|
|||||||
|
|
||||||
// operations on set of globals
|
// operations on set of globals
|
||||||
static inline void lfs_globalxor(lfs_global_t *a, const lfs_global_t *b) {
|
static inline void lfs_globalxor(lfs_global_t *a, const lfs_global_t *b) {
|
||||||
for (int i = 0; i < sizeof(lfs_global_t)/2; i++) {
|
for (int i = 0; i < sizeof(lfs_global_t)/4; i++) {
|
||||||
a->u16[i] ^= b->u16[i];
|
a->u32[i] ^= b->u32[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool lfs_globaliszero(const lfs_global_t *a) {
|
static inline bool lfs_globaliszero(const lfs_global_t *a) {
|
||||||
for (int i = 0; i < sizeof(lfs_global_t)/2; i++) {
|
for (int i = 0; i < sizeof(lfs_global_t)/4; i++) {
|
||||||
if (a->u16[i] != 0) {
|
if (a->u32[i] != 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -425,53 +424,26 @@ static inline bool lfs_globaliszero(const lfs_global_t *a) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void lfs_globalzero(lfs_global_t *a) {
|
static inline void lfs_globalzero(lfs_global_t *a) {
|
||||||
memset(a->u16, 0x00, sizeof(lfs_global_t));
|
lfs_globalxor(a, a);
|
||||||
}
|
|
||||||
|
|
||||||
static inline void lfs_globalones(lfs_global_t *a) {
|
|
||||||
memset(a->u16, 0xff, sizeof(lfs_global_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void lfs_globalxormove(lfs_global_t *a,
|
|
||||||
const lfs_block_t pair[2], uint16_t id) {
|
|
||||||
a->u16[0] ^= id;
|
|
||||||
for (int i = 0; i < sizeof(lfs_block_t[2])/2; i++) {
|
|
||||||
a->u16[1+i] ^= ((uint16_t*)pair)[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void lfs_globalxordeorphaned(lfs_global_t *a, bool deorphaned) {
|
|
||||||
a->u16[0] ^= deorphaned << 15;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void lfs_globalfromle32(lfs_global_t *a) {
|
static inline void lfs_globalfromle32(lfs_global_t *a) {
|
||||||
a->u16[0] = lfs_fromle16(a->u16[0]);
|
lfs_pairfromle32(a->s.movepair);
|
||||||
lfs_pairfromle32((lfs_block_t*)&a->u16[1]);
|
a->s.moveid = lfs_fromle16(a->s.moveid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void lfs_globaltole32(lfs_global_t *a) {
|
static inline void lfs_globaltole32(lfs_global_t *a) {
|
||||||
a->u16[0] = lfs_tole16(a->u16[0]);
|
lfs_pairtole32(a->s.movepair);
|
||||||
lfs_pairtole32((lfs_block_t*)&a->u16[1]);
|
a->s.moveid = lfs_tole16(a->s.moveid);
|
||||||
}
|
|
||||||
|
|
||||||
static inline const lfs_block_t *lfs_globalmovepair(const lfs_t *lfs) {
|
|
||||||
return (const lfs_block_t*)&lfs->globals.u16[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint16_t lfs_globalmoveid(const lfs_t *lfs) {
|
|
||||||
return 0x3ff & lfs->globals.u16[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool lfs_globalisdeorphaned(const lfs_t *lfs) {
|
|
||||||
return 0x8000 & lfs->globals.u16[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void lfs_globalmove(lfs_t *lfs,
|
static inline void lfs_globalmove(lfs_t *lfs,
|
||||||
const lfs_block_t pair[2], uint16_t id) {
|
const lfs_block_t pair[2], uint16_t id) {
|
||||||
lfs_global_t diff;
|
lfs_global_t diff;
|
||||||
lfs_globalzero(&diff);
|
lfs_globalzero(&diff);
|
||||||
lfs_globalxormove(&diff, lfs_globalmovepair(lfs), lfs_globalmoveid(lfs));
|
diff.s.movepair[0] ^= lfs->globals.s.movepair[0] ^ pair[0];
|
||||||
lfs_globalxormove(&diff, pair, id);
|
diff.s.movepair[1] ^= lfs->globals.s.movepair[1] ^ pair[1];
|
||||||
|
diff.s.moveid ^= lfs->globals.s.moveid ^ id;
|
||||||
lfs_globalfromle32(&lfs->locals);
|
lfs_globalfromle32(&lfs->locals);
|
||||||
lfs_globalxor(&lfs->locals, &diff);
|
lfs_globalxor(&lfs->locals, &diff);
|
||||||
lfs_globaltole32(&lfs->locals);
|
lfs_globaltole32(&lfs->locals);
|
||||||
@@ -479,11 +451,8 @@ static inline void lfs_globalmove(lfs_t *lfs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline void lfs_globaldeorphaned(lfs_t *lfs, bool deorphaned) {
|
static inline void lfs_globaldeorphaned(lfs_t *lfs, bool deorphaned) {
|
||||||
deorphaned ^= lfs_globalisdeorphaned(lfs);
|
lfs->locals.s.deorphaned ^= lfs->globals.s.deorphaned ^ deorphaned;
|
||||||
lfs_globalfromle32(&lfs->locals);
|
lfs->globals.s.deorphaned ^= lfs->globals.s.deorphaned ^ deorphaned;
|
||||||
lfs_globalxordeorphaned(&lfs->locals, deorphaned);
|
|
||||||
lfs_globaltole32(&lfs->locals);
|
|
||||||
lfs_globalxordeorphaned(&lfs->globals, deorphaned);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -696,7 +665,8 @@ static int lfs_commitglobals(lfs_t *lfs, struct lfs_commit *commit,
|
|||||||
|
|
||||||
lfs_globalxor(locals, &lfs->locals);
|
lfs_globalxor(locals, &lfs->locals);
|
||||||
int err = lfs_commitattr(lfs, commit,
|
int err = lfs_commitattr(lfs, commit,
|
||||||
LFS_MKTAG(LFS_TYPE_GLOBALS, 0x3ff, sizeof(lfs_global_t)), locals);
|
LFS_MKTAG(LFS_TYPE_GLOBALS + locals->s.deorphaned,
|
||||||
|
0x3ff, sizeof(lfs_global_t)), locals);
|
||||||
lfs_globalxor(locals, &lfs->locals);
|
lfs_globalxor(locals, &lfs->locals);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -893,6 +863,7 @@ static int32_t lfs_dir_find(lfs_t *lfs,
|
|||||||
}
|
}
|
||||||
lfs_pairfromle32(temptail);
|
lfs_pairfromle32(temptail);
|
||||||
} else if (lfs_tagsubtype(tag) == LFS_TYPE_GLOBALS) {
|
} else if (lfs_tagsubtype(tag) == LFS_TYPE_GLOBALS) {
|
||||||
|
templocals.s.deorphaned = (lfs_tagtype(tag) & 1);
|
||||||
err = lfs_bd_read(lfs, dir->pair[0], off+sizeof(tag),
|
err = lfs_bd_read(lfs, dir->pair[0], off+sizeof(tag),
|
||||||
&templocals, sizeof(templocals));
|
&templocals, sizeof(templocals));
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -929,11 +900,11 @@ static int32_t lfs_dir_find(lfs_t *lfs,
|
|||||||
// consider what we have good enough
|
// consider what we have good enough
|
||||||
if (dir->off > 0) {
|
if (dir->off > 0) {
|
||||||
// synthetic move
|
// synthetic move
|
||||||
if (lfs_paircmp(dir->pair, lfs_globalmovepair(lfs)) == 0) {
|
if (lfs_paircmp(dir->pair, lfs->globals.s.movepair) == 0) {
|
||||||
if (lfs_globalmoveid(lfs) == lfs_tagid(foundtag)) {
|
if (lfs->globals.s.moveid == lfs_tagid(foundtag)) {
|
||||||
foundtag = LFS_ERR_NOENT;
|
foundtag = LFS_ERR_NOENT;
|
||||||
} else if (lfs_tagisvalid(foundtag) &&
|
} else if (lfs_tagisvalid(foundtag) &&
|
||||||
lfs_globalmoveid(lfs) < lfs_tagid(foundtag)) {
|
lfs->globals.s.moveid < lfs_tagid(foundtag)) {
|
||||||
foundtag -= LFS_MKTAG(0, 1, 0);
|
foundtag -= LFS_MKTAG(0, 1, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -963,8 +934,8 @@ static int lfs_dir_fetch(lfs_t *lfs,
|
|||||||
static int32_t lfs_dir_get(lfs_t *lfs, lfs_mdir_t *dir,
|
static int32_t lfs_dir_get(lfs_t *lfs, lfs_mdir_t *dir,
|
||||||
uint32_t getmask, uint32_t gettag, void *buffer) {
|
uint32_t getmask, uint32_t gettag, void *buffer) {
|
||||||
int32_t getdiff = 0;
|
int32_t getdiff = 0;
|
||||||
if (lfs_paircmp(dir->pair, lfs_globalmovepair(lfs)) == 0 &&
|
if (lfs_paircmp(dir->pair, lfs->globals.s.movepair) == 0 &&
|
||||||
lfs_tagid(gettag) <= lfs_globalmoveid(lfs)) {
|
lfs_tagid(gettag) <= lfs->globals.s.moveid) {
|
||||||
// synthetic moves
|
// synthetic moves
|
||||||
getdiff = LFS_MKTAG(0, 1, 0);
|
getdiff = LFS_MKTAG(0, 1, 0);
|
||||||
}
|
}
|
||||||
@@ -1166,18 +1137,17 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
|
|||||||
lfs_mattr_t cancelattr;
|
lfs_mattr_t cancelattr;
|
||||||
lfs_global_t canceldiff;
|
lfs_global_t canceldiff;
|
||||||
lfs_globalzero(&canceldiff);
|
lfs_globalzero(&canceldiff);
|
||||||
if (lfs_paircmp(dir->pair, lfs_globalmovepair(lfs)) == 0) {
|
if (lfs_paircmp(dir->pair, lfs->globals.s.movepair) == 0) {
|
||||||
// Wait, we have the move? Just cancel this out here
|
// Wait, we have the move? Just cancel this out here
|
||||||
// We need to, or else the move can become outdated
|
// We need to, or else the move can become outdated
|
||||||
lfs_globalxormove(&canceldiff,
|
canceldiff.s.movepair[0] ^= lfs->globals.s.movepair[0] ^ 0xffffffff;
|
||||||
lfs_globalmovepair(lfs), lfs_globalmoveid(lfs));
|
canceldiff.s.movepair[1] ^= lfs->globals.s.movepair[1] ^ 0xffffffff;
|
||||||
lfs_globalxormove(&canceldiff,
|
canceldiff.s.moveid ^= lfs->globals.s.moveid ^ 0x3ff;
|
||||||
(lfs_block_t[2]){0xffffffff, 0xffffffff}, 0x3ff);
|
|
||||||
lfs_globalfromle32(&lfs->locals);
|
lfs_globalfromle32(&lfs->locals);
|
||||||
lfs_globalxor(&lfs->locals, &canceldiff);
|
lfs_globalxor(&lfs->locals, &canceldiff);
|
||||||
lfs_globaltole32(&lfs->locals);
|
lfs_globaltole32(&lfs->locals);
|
||||||
|
|
||||||
cancelattr.tag = LFS_MKTAG(LFS_TYPE_DELETE, lfs_globalmoveid(lfs), 0);
|
cancelattr.tag = LFS_MKTAG(LFS_TYPE_DELETE, lfs->globals.s.moveid, 0);
|
||||||
cancelattr.next = attrs;
|
cancelattr.next = attrs;
|
||||||
attrs = &cancelattr;
|
attrs = &cancelattr;
|
||||||
}
|
}
|
||||||
@@ -2814,7 +2784,10 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
lfs->root[0] = 0xffffffff;
|
lfs->root[0] = 0xffffffff;
|
||||||
lfs->root[1] = 0xffffffff;
|
lfs->root[1] = 0xffffffff;
|
||||||
lfs->mlist = NULL;
|
lfs->mlist = NULL;
|
||||||
lfs_globalones(&lfs->globals);
|
lfs->globals.s.movepair[0] = 0xffffffff;
|
||||||
|
lfs->globals.s.movepair[1] = 0xffffffff;
|
||||||
|
lfs->globals.s.moveid = 0x3ff;
|
||||||
|
lfs->globals.s.deorphaned = true;
|
||||||
lfs_globalzero(&lfs->locals);
|
lfs_globalzero(&lfs->locals);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2920,8 +2893,8 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
lfs_alloc_ack(lfs);
|
lfs_alloc_ack(lfs);
|
||||||
|
|
||||||
// load superblock
|
// load superblock
|
||||||
lfs_mdir_t dir;
|
lfs_mdir_t superdir;
|
||||||
err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1});
|
err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1});
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err == LFS_ERR_CORRUPT) {
|
if (err == LFS_ERR_CORRUPT) {
|
||||||
LFS_ERROR("Invalid superblock at %d %d", 0, 1);
|
LFS_ERROR("Invalid superblock at %d %d", 0, 1);
|
||||||
@@ -2930,7 +2903,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lfs_superblock_t superblock;
|
lfs_superblock_t superblock;
|
||||||
int32_t res = lfs_dir_get(lfs, &dir, 0x7ffff000,
|
int32_t res = lfs_dir_get(lfs, &superdir, 0x7ffff000,
|
||||||
LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, sizeof(superblock)),
|
LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, sizeof(superblock)),
|
||||||
&superblock);
|
&superblock);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
@@ -2951,7 +2924,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
return LFS_ERR_INVAL;
|
return LFS_ERR_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = lfs_dir_get(lfs, &dir, 0x7ffff000,
|
res = lfs_dir_get(lfs, &superdir, 0x7ffff000,
|
||||||
LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 0, sizeof(lfs->root)),
|
LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 0, sizeof(lfs->root)),
|
||||||
&lfs->root);
|
&lfs->root);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
@@ -2990,9 +2963,26 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// scan for any global updates
|
// scan for any global updates
|
||||||
err = lfs_fs_scan(lfs);
|
lfs_mdir_t dir = {.tail = {0, 1}};
|
||||||
if (err) {
|
while (!lfs_pairisnull(dir.tail)) {
|
||||||
return err;
|
int err = lfs_dir_fetch(lfs, &dir, dir.tail);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// xor together indirect deletes
|
||||||
|
lfs_globalxor(&lfs->locals, &dir.locals);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update littlefs with globals
|
||||||
|
lfs_globalfromle32(&lfs->locals);
|
||||||
|
lfs_globalxor(&lfs->globals, &lfs->locals);
|
||||||
|
lfs_globalzero(&lfs->locals);
|
||||||
|
if (!lfs_pairisnull(lfs->globals.s.movepair)) {
|
||||||
|
LFS_DEBUG("Found move %d %d %d",
|
||||||
|
lfs->globals.s.movepair[0],
|
||||||
|
lfs->globals.s.movepair[1],
|
||||||
|
lfs->globals.s.moveid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -3186,41 +3176,10 @@ static int lfs_fs_relocate(lfs_t *lfs,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lfs_fs_scan(lfs_t *lfs) {
|
|
||||||
if (lfs_pairisnull(lfs->root)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// iterate over all directory directory entries
|
|
||||||
lfs_mdir_t dir = {.tail = {0, 1}};
|
|
||||||
while (!lfs_pairisnull(dir.tail)) {
|
|
||||||
int err = lfs_dir_fetch(lfs, &dir, dir.tail);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// xor together indirect deletes
|
|
||||||
lfs_globalxor(&lfs->locals, &dir.locals);
|
|
||||||
}
|
|
||||||
|
|
||||||
// update littlefs with globals
|
|
||||||
lfs_globalfromle32(&lfs->locals);
|
|
||||||
lfs_globalxor(&lfs->globals, &lfs->locals);
|
|
||||||
lfs_globalzero(&lfs->locals);
|
|
||||||
if (!lfs_pairisnull(lfs_globalmovepair(lfs))) {
|
|
||||||
LFS_DEBUG("Found move %d %d %d",
|
|
||||||
lfs_globalmovepair(lfs)[0],
|
|
||||||
lfs_globalmovepair(lfs)[1],
|
|
||||||
lfs_globalmoveid(lfs));
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int lfs_fs_forceconsistency(lfs_t *lfs) {
|
static int lfs_fs_forceconsistency(lfs_t *lfs) {
|
||||||
if (!lfs_globalisdeorphaned(lfs)) {
|
if (!lfs->globals.s.deorphaned) {
|
||||||
LFS_DEBUG("Found orphans %d",
|
LFS_DEBUG("Found orphans %d",
|
||||||
lfs_globalisdeorphaned(lfs));
|
lfs->globals.s.deorphaned);
|
||||||
|
|
||||||
// Fix any orphans
|
// Fix any orphans
|
||||||
lfs_mdir_t pdir = {.split = true};
|
lfs_mdir_t pdir = {.split = true};
|
||||||
@@ -3292,16 +3251,16 @@ static int lfs_fs_forceconsistency(lfs_t *lfs) {
|
|||||||
lfs_globaldeorphaned(lfs, false);
|
lfs_globaldeorphaned(lfs, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lfs_globalmoveid(lfs) != 0x3ff) {
|
if (lfs->globals.s.moveid != 0x3ff) {
|
||||||
// Fix bad moves
|
// Fix bad moves
|
||||||
LFS_DEBUG("Fixing move %d %d %d",
|
LFS_DEBUG("Fixing move %d %d %d",
|
||||||
lfs_globalmovepair(lfs)[0],
|
lfs->globals.s.movepair[0],
|
||||||
lfs_globalmovepair(lfs)[1],
|
lfs->globals.s.movepair[1],
|
||||||
lfs_globalmoveid(lfs));
|
lfs->globals.s.moveid);
|
||||||
|
|
||||||
// fetch and delete the moved entry
|
// fetch and delete the moved entry
|
||||||
lfs_mdir_t movedir;
|
lfs_mdir_t movedir;
|
||||||
int err = lfs_dir_fetch(lfs, &movedir, lfs_globalmovepair(lfs));
|
int err = lfs_dir_fetch(lfs, &movedir, lfs->globals.s.movepair);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|||||||
9
lfs.h
9
lfs.h
@@ -287,18 +287,23 @@ typedef struct lfs_cache {
|
|||||||
} lfs_cache_t;
|
} lfs_cache_t;
|
||||||
|
|
||||||
typedef union lfs_global {
|
typedef union lfs_global {
|
||||||
uint16_t u16[5];
|
uint32_t u32[3];
|
||||||
|
struct {
|
||||||
|
lfs_block_t movepair[2];
|
||||||
|
uint16_t moveid;
|
||||||
|
bool deorphaned;
|
||||||
|
} s;
|
||||||
} lfs_global_t;
|
} lfs_global_t;
|
||||||
|
|
||||||
typedef struct lfs_mdir {
|
typedef struct lfs_mdir {
|
||||||
lfs_block_t pair[2];
|
lfs_block_t pair[2];
|
||||||
lfs_block_t tail[2];
|
|
||||||
uint32_t rev;
|
uint32_t rev;
|
||||||
uint32_t etag;
|
uint32_t etag;
|
||||||
lfs_off_t off;
|
lfs_off_t off;
|
||||||
uint16_t count;
|
uint16_t count;
|
||||||
bool erased;
|
bool erased;
|
||||||
bool split;
|
bool split;
|
||||||
|
lfs_block_t tail[2];
|
||||||
lfs_global_t locals;
|
lfs_global_t locals;
|
||||||
} lfs_mdir_t;
|
} lfs_mdir_t;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user