Skip to content

Commit 97f35c3

Browse files
committed
Simplified the internal xored-globals implementation
There wasn't much use (and inconsistent compiler support) for storing small values next to the unaligned lfs_global_t struct. So instead, I've rounded the struct up to the nearest word to try to take advantage of the alignment in xor and memset operations. I've also moved the global fetching into lfs_mount, since that was the only use of the operation. This allows for some variable reuse in the mount function.
1 parent 35f68d2 commit 97f35c3

File tree

2 files changed

+69
-105
lines changed

2 files changed

+69
-105
lines changed

lfs.c

+62-103
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,6 @@ static int32_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t dir[2],
265265
lfs_mdir_t *parent);
266266
static int lfs_fs_relocate(lfs_t *lfs,
267267
const lfs_block_t oldpair[2], lfs_block_t newpair[2]);
268-
static int lfs_fs_scan(lfs_t *lfs);
269268
static int lfs_fs_forceconsistency(lfs_t *lfs);
270269

271270

@@ -410,80 +409,50 @@ static inline lfs_size_t lfs_tagsize(uint32_t tag) {
410409

411410
// operations on set of globals
412411
static inline void lfs_globalxor(lfs_global_t *a, const lfs_global_t *b) {
413-
for (int i = 0; i < sizeof(lfs_global_t)/2; i++) {
414-
a->u16[i] ^= b->u16[i];
412+
for (int i = 0; i < sizeof(lfs_global_t)/4; i++) {
413+
a->u32[i] ^= b->u32[i];
415414
}
416415
}
417416

418417
static inline bool lfs_globaliszero(const lfs_global_t *a) {
419-
for (int i = 0; i < sizeof(lfs_global_t)/2; i++) {
420-
if (a->u16[i] != 0) {
418+
for (int i = 0; i < sizeof(lfs_global_t)/4; i++) {
419+
if (a->u32[i] != 0) {
421420
return false;
422421
}
423422
}
424423
return true;
425424
}
426425

427426
static inline void lfs_globalzero(lfs_global_t *a) {
428-
memset(a->u16, 0x00, sizeof(lfs_global_t));
429-
}
430-
431-
static inline void lfs_globalones(lfs_global_t *a) {
432-
memset(a->u16, 0xff, sizeof(lfs_global_t));
433-
}
434-
435-
static inline void lfs_globalxormove(lfs_global_t *a,
436-
const lfs_block_t pair[2], uint16_t id) {
437-
a->u16[0] ^= id;
438-
for (int i = 0; i < sizeof(lfs_block_t[2])/2; i++) {
439-
a->u16[1+i] ^= ((uint16_t*)pair)[i];
440-
}
441-
}
442-
443-
static inline void lfs_globalxordeorphaned(lfs_global_t *a, bool deorphaned) {
444-
a->u16[0] ^= deorphaned << 15;
427+
lfs_globalxor(a, a);
445428
}
446429

447430
static inline void lfs_globalfromle32(lfs_global_t *a) {
448-
a->u16[0] = lfs_fromle16(a->u16[0]);
449-
lfs_pairfromle32((lfs_block_t*)&a->u16[1]);
431+
lfs_pairfromle32(a->s.movepair);
432+
a->s.moveid = lfs_fromle16(a->s.moveid);
450433
}
451434

452435
static inline void lfs_globaltole32(lfs_global_t *a) {
453-
a->u16[0] = lfs_tole16(a->u16[0]);
454-
lfs_pairtole32((lfs_block_t*)&a->u16[1]);
455-
}
456-
457-
static inline const lfs_block_t *lfs_globalmovepair(const lfs_t *lfs) {
458-
return (const lfs_block_t*)&lfs->globals.u16[1];
459-
}
460-
461-
static inline uint16_t lfs_globalmoveid(const lfs_t *lfs) {
462-
return 0x3ff & lfs->globals.u16[0];
463-
}
464-
465-
static inline bool lfs_globalisdeorphaned(const lfs_t *lfs) {
466-
return 0x8000 & lfs->globals.u16[0];
436+
lfs_pairtole32(a->s.movepair);
437+
a->s.moveid = lfs_tole16(a->s.moveid);
467438
}
468439

469440
static inline void lfs_globalmove(lfs_t *lfs,
470441
const lfs_block_t pair[2], uint16_t id) {
471442
lfs_global_t diff;
472443
lfs_globalzero(&diff);
473-
lfs_globalxormove(&diff, lfs_globalmovepair(lfs), lfs_globalmoveid(lfs));
474-
lfs_globalxormove(&diff, pair, id);
444+
diff.s.movepair[0] ^= lfs->globals.s.movepair[0] ^ pair[0];
445+
diff.s.movepair[1] ^= lfs->globals.s.movepair[1] ^ pair[1];
446+
diff.s.moveid ^= lfs->globals.s.moveid ^ id;
475447
lfs_globalfromle32(&lfs->locals);
476448
lfs_globalxor(&lfs->locals, &diff);
477449
lfs_globaltole32(&lfs->locals);
478450
lfs_globalxor(&lfs->globals, &diff);
479451
}
480452

481453
static inline void lfs_globaldeorphaned(lfs_t *lfs, bool deorphaned) {
482-
deorphaned ^= lfs_globalisdeorphaned(lfs);
483-
lfs_globalfromle32(&lfs->locals);
484-
lfs_globalxordeorphaned(&lfs->locals, deorphaned);
485-
lfs_globaltole32(&lfs->locals);
486-
lfs_globalxordeorphaned(&lfs->globals, deorphaned);
454+
lfs->locals.s.deorphaned ^= lfs->globals.s.deorphaned ^ deorphaned;
455+
lfs->globals.s.deorphaned ^= lfs->globals.s.deorphaned ^ deorphaned;
487456
}
488457

489458

@@ -696,7 +665,8 @@ static int lfs_commitglobals(lfs_t *lfs, struct lfs_commit *commit,
696665

697666
lfs_globalxor(locals, &lfs->locals);
698667
int err = lfs_commitattr(lfs, commit,
699-
LFS_MKTAG(LFS_TYPE_GLOBALS, 0x3ff, sizeof(lfs_global_t)), locals);
668+
LFS_MKTAG(LFS_TYPE_GLOBALS + locals->s.deorphaned,
669+
0x3ff, sizeof(lfs_global_t)), locals);
700670
lfs_globalxor(locals, &lfs->locals);
701671
return err;
702672
}
@@ -893,6 +863,7 @@ static int32_t lfs_dir_find(lfs_t *lfs,
893863
}
894864
lfs_pairfromle32(temptail);
895865
} else if (lfs_tagsubtype(tag) == LFS_TYPE_GLOBALS) {
866+
templocals.s.deorphaned = (lfs_tagtype(tag) & 1);
896867
err = lfs_bd_read(lfs, dir->pair[0], off+sizeof(tag),
897868
&templocals, sizeof(templocals));
898869
if (err) {
@@ -929,11 +900,11 @@ static int32_t lfs_dir_find(lfs_t *lfs,
929900
// consider what we have good enough
930901
if (dir->off > 0) {
931902
// synthetic move
932-
if (lfs_paircmp(dir->pair, lfs_globalmovepair(lfs)) == 0) {
933-
if (lfs_globalmoveid(lfs) == lfs_tagid(foundtag)) {
903+
if (lfs_paircmp(dir->pair, lfs->globals.s.movepair) == 0) {
904+
if (lfs->globals.s.moveid == lfs_tagid(foundtag)) {
934905
foundtag = LFS_ERR_NOENT;
935906
} else if (lfs_tagisvalid(foundtag) &&
936-
lfs_globalmoveid(lfs) < lfs_tagid(foundtag)) {
907+
lfs->globals.s.moveid < lfs_tagid(foundtag)) {
937908
foundtag -= LFS_MKTAG(0, 1, 0);
938909
}
939910
}
@@ -963,8 +934,8 @@ static int lfs_dir_fetch(lfs_t *lfs,
963934
static int32_t lfs_dir_get(lfs_t *lfs, lfs_mdir_t *dir,
964935
uint32_t getmask, uint32_t gettag, void *buffer) {
965936
int32_t getdiff = 0;
966-
if (lfs_paircmp(dir->pair, lfs_globalmovepair(lfs)) == 0 &&
967-
lfs_tagid(gettag) <= lfs_globalmoveid(lfs)) {
937+
if (lfs_paircmp(dir->pair, lfs->globals.s.movepair) == 0 &&
938+
lfs_tagid(gettag) <= lfs->globals.s.moveid) {
968939
// synthetic moves
969940
getdiff = LFS_MKTAG(0, 1, 0);
970941
}
@@ -1166,18 +1137,17 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
11661137
lfs_mattr_t cancelattr;
11671138
lfs_global_t canceldiff;
11681139
lfs_globalzero(&canceldiff);
1169-
if (lfs_paircmp(dir->pair, lfs_globalmovepair(lfs)) == 0) {
1140+
if (lfs_paircmp(dir->pair, lfs->globals.s.movepair) == 0) {
11701141
// Wait, we have the move? Just cancel this out here
11711142
// We need to, or else the move can become outdated
1172-
lfs_globalxormove(&canceldiff,
1173-
lfs_globalmovepair(lfs), lfs_globalmoveid(lfs));
1174-
lfs_globalxormove(&canceldiff,
1175-
(lfs_block_t[2]){0xffffffff, 0xffffffff}, 0x3ff);
1143+
canceldiff.s.movepair[0] ^= lfs->globals.s.movepair[0] ^ 0xffffffff;
1144+
canceldiff.s.movepair[1] ^= lfs->globals.s.movepair[1] ^ 0xffffffff;
1145+
canceldiff.s.moveid ^= lfs->globals.s.moveid ^ 0x3ff;
11761146
lfs_globalfromle32(&lfs->locals);
11771147
lfs_globalxor(&lfs->locals, &canceldiff);
11781148
lfs_globaltole32(&lfs->locals);
11791149

1180-
cancelattr.tag = LFS_MKTAG(LFS_TYPE_DELETE, lfs_globalmoveid(lfs), 0);
1150+
cancelattr.tag = LFS_MKTAG(LFS_TYPE_DELETE, lfs->globals.s.moveid, 0);
11811151
cancelattr.next = attrs;
11821152
attrs = &cancelattr;
11831153
}
@@ -2814,7 +2784,10 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
28142784
lfs->root[0] = 0xffffffff;
28152785
lfs->root[1] = 0xffffffff;
28162786
lfs->mlist = NULL;
2817-
lfs_globalones(&lfs->globals);
2787+
lfs->globals.s.movepair[0] = 0xffffffff;
2788+
lfs->globals.s.movepair[1] = 0xffffffff;
2789+
lfs->globals.s.moveid = 0x3ff;
2790+
lfs->globals.s.deorphaned = true;
28182791
lfs_globalzero(&lfs->locals);
28192792

28202793
return 0;
@@ -2920,8 +2893,8 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
29202893
lfs_alloc_ack(lfs);
29212894

29222895
// load superblock
2923-
lfs_mdir_t dir;
2924-
err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1});
2896+
lfs_mdir_t superdir;
2897+
err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1});
29252898
if (err) {
29262899
if (err == LFS_ERR_CORRUPT) {
29272900
LFS_ERROR("Invalid superblock at %d %d", 0, 1);
@@ -2930,7 +2903,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
29302903
}
29312904

29322905
lfs_superblock_t superblock;
2933-
int32_t res = lfs_dir_get(lfs, &dir, 0x7ffff000,
2906+
int32_t res = lfs_dir_get(lfs, &superdir, 0x7ffff000,
29342907
LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, sizeof(superblock)),
29352908
&superblock);
29362909
if (res < 0) {
@@ -2951,7 +2924,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
29512924
return LFS_ERR_INVAL;
29522925
}
29532926

2954-
res = lfs_dir_get(lfs, &dir, 0x7ffff000,
2927+
res = lfs_dir_get(lfs, &superdir, 0x7ffff000,
29552928
LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 0, sizeof(lfs->root)),
29562929
&lfs->root);
29572930
if (res < 0) {
@@ -2990,9 +2963,26 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
29902963
}
29912964

29922965
// scan for any global updates
2993-
err = lfs_fs_scan(lfs);
2994-
if (err) {
2995-
return err;
2966+
lfs_mdir_t dir = {.tail = {0, 1}};
2967+
while (!lfs_pairisnull(dir.tail)) {
2968+
int err = lfs_dir_fetch(lfs, &dir, dir.tail);
2969+
if (err) {
2970+
return err;
2971+
}
2972+
2973+
// xor together indirect deletes
2974+
lfs_globalxor(&lfs->locals, &dir.locals);
2975+
}
2976+
2977+
// update littlefs with globals
2978+
lfs_globalfromle32(&lfs->locals);
2979+
lfs_globalxor(&lfs->globals, &lfs->locals);
2980+
lfs_globalzero(&lfs->locals);
2981+
if (!lfs_pairisnull(lfs->globals.s.movepair)) {
2982+
LFS_DEBUG("Found move %d %d %d",
2983+
lfs->globals.s.movepair[0],
2984+
lfs->globals.s.movepair[1],
2985+
lfs->globals.s.moveid);
29962986
}
29972987

29982988
return 0;
@@ -3186,41 +3176,10 @@ static int lfs_fs_relocate(lfs_t *lfs,
31863176
return 0;
31873177
}
31883178

3189-
static int lfs_fs_scan(lfs_t *lfs) {
3190-
if (lfs_pairisnull(lfs->root)) {
3191-
return 0;
3192-
}
3193-
3194-
// iterate over all directory directory entries
3195-
lfs_mdir_t dir = {.tail = {0, 1}};
3196-
while (!lfs_pairisnull(dir.tail)) {
3197-
int err = lfs_dir_fetch(lfs, &dir, dir.tail);
3198-
if (err) {
3199-
return err;
3200-
}
3201-
3202-
// xor together indirect deletes
3203-
lfs_globalxor(&lfs->locals, &dir.locals);
3204-
}
3205-
3206-
// update littlefs with globals
3207-
lfs_globalfromle32(&lfs->locals);
3208-
lfs_globalxor(&lfs->globals, &lfs->locals);
3209-
lfs_globalzero(&lfs->locals);
3210-
if (!lfs_pairisnull(lfs_globalmovepair(lfs))) {
3211-
LFS_DEBUG("Found move %d %d %d",
3212-
lfs_globalmovepair(lfs)[0],
3213-
lfs_globalmovepair(lfs)[1],
3214-
lfs_globalmoveid(lfs));
3215-
}
3216-
3217-
return 0;
3218-
}
3219-
32203179
static int lfs_fs_forceconsistency(lfs_t *lfs) {
3221-
if (!lfs_globalisdeorphaned(lfs)) {
3180+
if (!lfs->globals.s.deorphaned) {
32223181
LFS_DEBUG("Found orphans %d",
3223-
lfs_globalisdeorphaned(lfs));
3182+
lfs->globals.s.deorphaned);
32243183

32253184
// Fix any orphans
32263185
lfs_mdir_t pdir = {.split = true};
@@ -3292,16 +3251,16 @@ static int lfs_fs_forceconsistency(lfs_t *lfs) {
32923251
lfs_globaldeorphaned(lfs, false);
32933252
}
32943253

3295-
if (lfs_globalmoveid(lfs) != 0x3ff) {
3254+
if (lfs->globals.s.moveid != 0x3ff) {
32963255
// Fix bad moves
32973256
LFS_DEBUG("Fixing move %d %d %d",
3298-
lfs_globalmovepair(lfs)[0],
3299-
lfs_globalmovepair(lfs)[1],
3300-
lfs_globalmoveid(lfs));
3257+
lfs->globals.s.movepair[0],
3258+
lfs->globals.s.movepair[1],
3259+
lfs->globals.s.moveid);
33013260

33023261
// fetch and delete the moved entry
33033262
lfs_mdir_t movedir;
3304-
int err = lfs_dir_fetch(lfs, &movedir, lfs_globalmovepair(lfs));
3263+
int err = lfs_dir_fetch(lfs, &movedir, lfs->globals.s.movepair);
33053264
if (err) {
33063265
return err;
33073266
}

lfs.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -287,18 +287,23 @@ typedef struct lfs_cache {
287287
} lfs_cache_t;
288288

289289
typedef union lfs_global {
290-
uint16_t u16[5];
290+
uint32_t u32[3];
291+
struct {
292+
lfs_block_t movepair[2];
293+
uint16_t moveid;
294+
bool deorphaned;
295+
} s;
291296
} lfs_global_t;
292297

293298
typedef struct lfs_mdir {
294299
lfs_block_t pair[2];
295-
lfs_block_t tail[2];
296300
uint32_t rev;
297301
uint32_t etag;
298302
lfs_off_t off;
299303
uint16_t count;
300304
bool erased;
301305
bool split;
306+
lfs_block_t tail[2];
302307
lfs_global_t locals;
303308
} lfs_mdir_t;
304309

0 commit comments

Comments
 (0)