Skip to content

Commit 5ee84a6

Browse files
committed
WIP Added expading superblocks and root entries
1 parent e0e2892 commit 5ee84a6

File tree

6 files changed

+145
-136
lines changed

6 files changed

+145
-136
lines changed

lfs.c

Lines changed: 102 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,25 @@ static void lfs_ctz_tole32(struct lfs_ctz *ctz) {
377377
ctz->size = lfs_tole32(ctz->size);
378378
}
379379

380+
static inline void lfs_superblock_fromle32(lfs_superblock_t *superblock) {
381+
superblock->version = lfs_fromle32(superblock->version);
382+
superblock->block_size = lfs_fromle32(superblock->block_size);
383+
superblock->block_count = lfs_fromle32(superblock->block_count);
384+
superblock->inline_max = lfs_fromle32(superblock->inline_max);
385+
superblock->attr_max = lfs_fromle32(superblock->attr_max);
386+
superblock->name_max = lfs_fromle32(superblock->name_max);
387+
}
388+
389+
static inline void lfs_superblock_tole32(lfs_superblock_t *superblock) {
390+
superblock->version = lfs_tole32(superblock->version);
391+
superblock->block_size = lfs_tole32(superblock->block_size);
392+
superblock->block_count = lfs_tole32(superblock->block_count);
393+
superblock->inline_max = lfs_tole32(superblock->inline_max);
394+
superblock->attr_max = lfs_tole32(superblock->attr_max);
395+
superblock->name_max = lfs_tole32(superblock->name_max);
396+
}
397+
398+
380399

381400
/// Entry tag operations ///
382401
#define LFS_MKTAG(type, id, size) \
@@ -524,15 +543,15 @@ static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit,
524543

525544
static int lfs_commit_attr(lfs_t *lfs, struct lfs_commit *commit,
526545
uint32_t tag, const void *buffer) {
527-
if (lfs_tag_type(tag) == LFS_FROM_ATTRS) {
528-
// special case for custom attributes
529-
return lfs_commit_attrs(lfs, commit,
530-
lfs_tag_id(tag), buffer);
531-
} else if (lfs_tag_type(tag) == LFS_FROM_MOVE) {
546+
if (lfs_tag_subtype(tag) == LFS_FROM_MOVE) {
532547
// special case for moves
533548
return lfs_commit_move(lfs, commit,
534549
lfs_tag_size(tag), lfs_tag_id(tag),
535550
buffer, NULL);
551+
} else if (lfs_tag_subtype(tag) == LFS_FROM_ATTRS) {
552+
// special case for custom attributes
553+
return lfs_commit_attrs(lfs, commit,
554+
lfs_tag_id(tag), buffer);
536555
}
537556

538557
// check if we fit
@@ -628,7 +647,8 @@ static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit,
628647
tag |= 0x80000000;
629648
}
630649

631-
if (lfs_tag_type(tag) == LFS_TYPE_DELETE && lfs_tag_id(tag) <= fromid) {
650+
if (lfs_tag_type(tag) == LFS_TYPE_DELETE &&
651+
lfs_tag_id(tag) <= fromid) {
632652
// something was deleted, we need to move around it
633653
fromid += 1;
634654
} else if (lfs_tag_id(tag) != fromid) {
@@ -667,8 +687,8 @@ static int lfs_commit_globals(lfs_t *lfs, struct lfs_commit *commit,
667687

668688
lfs_global_xor(locals, &lfs->locals);
669689
int err = lfs_commit_attr(lfs, commit,
670-
LFS_MKTAG(LFS_TYPE_GLOBALS + locals->s.deorphaned,
671-
0x3ff, sizeof(lfs_global_t)), locals);
690+
LFS_MKTAG(LFS_TYPE_GLOBALS + locals->s.deorphaned, 0x3ff, 10),
691+
locals);
672692
lfs_global_xor(locals, &lfs->locals);
673693
return err;
674694
}
@@ -726,7 +746,7 @@ static int lfs_commit_crc(lfs_t *lfs, struct lfs_commit *commit) {
726746

727747
// internal dir operations
728748
static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) {
729-
// allocate pair of dir blocks (backwards, so we write to block 1 first)
749+
// allocate pair of dir blocks (backwards, so we write block 1 first)
730750
for (int i = 0; i < 2; i++) {
731751
int err = lfs_alloc(lfs, &dir->pair[(i+1)%2]);
732752
if (err) {
@@ -756,10 +776,9 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) {
756776
return 0;
757777
}
758778

759-
static int32_t lfs_dir_find(lfs_t *lfs,
779+
static int32_t lfs_dir_fetchmatch(lfs_t *lfs,
760780
lfs_mdir_t *dir, const lfs_block_t pair[2],
761-
uint32_t findmask, uint32_t findtag,
762-
const void *findbuffer) {
781+
uint32_t findmask, uint32_t findtag, const void *findbuffer) {
763782
dir->pair[0] = pair[0];
764783
dir->pair[1] = pair[1];
765784
int32_t foundtag = LFS_ERR_NOENT;
@@ -887,7 +906,7 @@ static int32_t lfs_dir_find(lfs_t *lfs,
887906
} else if (lfs_tag_subtype(tag) == LFS_TYPE_GLOBALS) {
888907
templocals.s.deorphaned = (lfs_tag_type(tag) & 1);
889908
err = lfs_bd_read(lfs, dir->pair[0], off+sizeof(tag),
890-
&templocals, sizeof(templocals));
909+
&templocals, 10);
891910
if (err) {
892911
if (err == LFS_ERR_CORRUPT) {
893912
dir->erased = false;
@@ -906,7 +925,7 @@ static int32_t lfs_dir_find(lfs_t *lfs,
906925
}
907926
} else if ((tag & findmask) == (findtag & findmask)) {
908927
int res = lfs_bd_cmp(lfs, dir->pair[0], off+sizeof(tag),
909-
findbuffer, lfs_tag_size(tag));
928+
findbuffer, lfs_tag_size(findtag));
910929
if (res < 0) {
911930
if (res == LFS_ERR_CORRUPT) {
912931
dir->erased = false;
@@ -953,14 +972,32 @@ static int32_t lfs_dir_find(lfs_t *lfs,
953972

954973
static int lfs_dir_fetch(lfs_t *lfs,
955974
lfs_mdir_t *dir, const lfs_block_t pair[2]) {
956-
int32_t res = lfs_dir_find(lfs, dir, pair, 0xffffffff, 0xffffffff, NULL);
975+
int32_t res = lfs_dir_fetchmatch(lfs, dir, pair,
976+
0xffffffff, 0xffffffff, NULL);
957977
if (res < 0 && res != LFS_ERR_NOENT) {
958978
return res;
959979
}
960980

961981
return 0;
962982
}
963983

984+
static int32_t lfs_dir_find(lfs_t *lfs,
985+
lfs_mdir_t *dir, const lfs_block_t pair[2], bool fs,
986+
uint32_t findmask, uint32_t findtag, const void *findbuffer) {
987+
dir->split = true;
988+
dir->tail[0] = pair[0];
989+
dir->tail[1] = pair[1];
990+
while ((dir->split || fs) && !lfs_pair_isnull(dir->tail)) {
991+
int32_t tag = lfs_dir_fetchmatch(lfs, dir, dir->tail,
992+
findmask, findtag, findbuffer);
993+
if (tag != LFS_ERR_NOENT) {
994+
return tag;
995+
}
996+
}
997+
998+
return LFS_ERR_NOENT;
999+
}
1000+
9641001
static int32_t lfs_dir_get(lfs_t *lfs, lfs_mdir_t *dir,
9651002
uint32_t getmask, uint32_t gettag, void *buffer) {
9661003
int32_t getdiff = 0;
@@ -979,6 +1016,8 @@ static int lfs_dir_compact(lfs_t *lfs,
9791016
lfs_mdir_t *source, uint16_t begin, uint16_t end) {
9801017
// save some state in case block is bad
9811018
const lfs_block_t oldpair[2] = {dir->pair[1], dir->pair[0]};
1019+
int16_t ack;
1020+
bool expanding = false;
9821021
bool relocated = false;
9831022

9841023
// There's nothing special about our global delta, so feed it back
@@ -989,9 +1028,25 @@ static int lfs_dir_compact(lfs_t *lfs,
9891028
// increment revision count
9901029
dir->rev += 1;
9911030

1031+
if (lfs_pair_cmp(dir->pair, (const lfs_block_t[2]){0, 1}) == 0 &&
1032+
dir->rev % 16 == 0) {
1033+
// we're writing too much to the superblock, should we expand?
1034+
lfs_ssize_t res = lfs_fs_size(lfs);
1035+
if (res < 0) {
1036+
return res;
1037+
}
1038+
1039+
// do we have enough space to expand?
1040+
if (res < lfs->cfg->block_count) {
1041+
expanding = (lfs_pair_cmp(dir->pair, lfs->root) != 0);
1042+
ack = 0;
1043+
goto split;
1044+
}
1045+
}
1046+
9921047
while (true) {
9931048
// last complete id
994-
int16_t ack = -1;
1049+
ack = -1;
9951050
dir->count = end - begin;
9961051

9971052
if (true) {
@@ -1111,7 +1166,7 @@ static int lfs_dir_compact(lfs_t *lfs,
11111166
tail.tail[0] = dir->tail[0];
11121167
tail.tail[1] = dir->tail[1];
11131168

1114-
err = lfs_dir_compact(lfs, &tail, attrs, dir, ack+1, end);
1169+
err = lfs_dir_compact(lfs, &tail, attrs, dir, ack+1-expanding, end);
11151170
if (err) {
11161171
return err;
11171172
}
@@ -1390,25 +1445,10 @@ static int32_t lfs_dir_lookup(lfs_t *lfs, lfs_mdir_t *dir, const char **path) {
13901445
}
13911446

13921447
// find entry matching name
1393-
while (true) {
1394-
tag = lfs_dir_find(lfs, dir, pair, 0x7c000fff,
1395-
LFS_MKTAG(LFS_TYPE_NAME, 0, namelen), name);
1396-
if (tag < 0 && tag != LFS_ERR_NOENT) {
1397-
return tag;
1398-
}
1399-
1400-
if (tag != LFS_ERR_NOENT) {
1401-
// found it
1402-
break;
1403-
}
1404-
1405-
if (!dir->split) {
1406-
// couldn't find it
1407-
return LFS_ERR_NOENT;
1408-
}
1409-
1410-
pair[0] = dir->tail[0];
1411-
pair[1] = dir->tail[1];
1448+
tag = lfs_dir_find(lfs, dir, pair, false, 0x7c000fff,
1449+
LFS_MKTAG(LFS_TYPE_NAME, 0, namelen), name);
1450+
if (tag < 0) {
1451+
return tag;
14121452
}
14131453

14141454
// to next name
@@ -2721,24 +2761,6 @@ int lfs_setattr(lfs_t *lfs, const char *path,
27212761

27222762

27232763
/// Filesystem operations ///
2724-
static inline void lfs_superblockfromle32(lfs_superblock_t *superblock) {
2725-
superblock->version = lfs_fromle32(superblock->version);
2726-
superblock->block_size = lfs_fromle32(superblock->block_size);
2727-
superblock->block_count = lfs_fromle32(superblock->block_count);
2728-
superblock->inline_max = lfs_fromle32(superblock->inline_max);
2729-
superblock->attr_max = lfs_fromle32(superblock->attr_max);
2730-
superblock->name_max = lfs_fromle32(superblock->name_max);
2731-
}
2732-
2733-
static inline void lfs_superblocktole32(lfs_superblock_t *superblock) {
2734-
superblock->version = lfs_tole32(superblock->version);
2735-
superblock->block_size = lfs_tole32(superblock->block_size);
2736-
superblock->block_count = lfs_tole32(superblock->block_count);
2737-
superblock->inline_max = lfs_tole32(superblock->inline_max);
2738-
superblock->attr_max = lfs_tole32(superblock->attr_max);
2739-
superblock->name_max = lfs_tole32(superblock->name_max);
2740-
}
2741-
27422764
static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
27432765
lfs->cfg = cfg;
27442766
int err = 0;
@@ -2859,30 +2881,13 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
28592881
lfs->free.i = 0;
28602882
lfs_alloc_ack(lfs);
28612883

2862-
// create superblock dir
2863-
lfs_mdir_t dir;
2864-
err = lfs_dir_alloc(lfs, &dir);
2865-
if (err) {
2866-
goto cleanup;
2867-
}
2868-
2869-
// write root directory
2884+
// create root dir
28702885
lfs_mdir_t root;
28712886
err = lfs_dir_alloc(lfs, &root);
28722887
if (err) {
28732888
goto cleanup;
28742889
}
28752890

2876-
err = lfs_dir_commit(lfs, &root, NULL);
2877-
if (err) {
2878-
goto cleanup;
2879-
}
2880-
2881-
lfs->root[0] = root.pair[0];
2882-
lfs->root[1] = root.pair[1];
2883-
dir.tail[0] = lfs->root[0];
2884-
dir.tail[1] = lfs->root[1];
2885-
28862891
// write one superblock
28872892
lfs_superblock_t superblock = {
28882893
.magic = {"littlefs"},
@@ -2895,20 +2900,17 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
28952900
.inline_max = lfs->inline_max,
28962901
};
28972902

2898-
lfs_superblocktole32(&superblock);
2899-
lfs_pair_tole32(lfs->root);
2900-
err = lfs_dir_commit(lfs, &dir,
2903+
lfs_superblock_tole32(&superblock);
2904+
err = lfs_dir_commit(lfs, &root,
29012905
LFS_MKATTR(LFS_TYPE_SUPERBLOCK, 0, &superblock, sizeof(superblock),
2902-
LFS_MKATTR(LFS_TYPE_DIRSTRUCT, 0, lfs->root, sizeof(lfs->root),
2906+
LFS_MKATTR(LFS_TYPE_ROOT, 1, NULL, 0,
29032907
NULL)));
2904-
lfs_pair_fromle32(lfs->root);
2905-
lfs_superblockfromle32(&superblock);
29062908
if (err) {
29072909
goto cleanup;
29082910
}
29092911

29102912
// sanity check that fetch works
2911-
err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1});
2913+
err = lfs_dir_fetch(lfs, &root, (const lfs_block_t[2]){0, 1});
29122914
if (err) {
29132915
goto cleanup;
29142916
}
@@ -2931,27 +2933,34 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
29312933
lfs_alloc_ack(lfs);
29322934

29332935
// load superblock
2934-
lfs_mdir_t superdir;
2935-
err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1});
2936+
lfs_mdir_t root;
2937+
err = lfs_dir_fetch(lfs, &root, (const lfs_block_t[2]){0, 1});
29362938
if (err) {
2937-
goto cleanup;
2939+
return err;
29382940
}
29392941

29402942
lfs_superblock_t superblock;
2941-
int32_t res = lfs_dir_get(lfs, &superdir, 0x7ffff000,
2943+
int32_t res = lfs_dir_get(lfs, &root, 0x7fc00000,
29422944
LFS_MKTAG(LFS_TYPE_SUPERBLOCK, 0, sizeof(superblock)),
29432945
&superblock);
29442946
if (res < 0) {
29452947
err = res;
29462948
goto cleanup;
29472949
}
2948-
lfs_superblockfromle32(&superblock);
2950+
lfs_superblock_fromle32(&superblock);
29492951

2950-
if (memcmp(superblock.magic, "littlefs", 8) != 0) {
2951-
LFS_ERROR("Invalid superblock \"%.8s\"", superblock.magic);
2952-
return LFS_ERR_INVAL;
2952+
// find root
2953+
int32_t tag = lfs_dir_find(lfs,
2954+
&root, (const lfs_block_t[2]){0, 1}, false, 0x7fc00000,
2955+
LFS_MKTAG(LFS_TYPE_ROOT, 0, 0), NULL);
2956+
if (tag < 0) {
2957+
return tag;
29532958
}
29542959

2960+
lfs->root[0] = root.pair[0];
2961+
lfs->root[1] = root.pair[1];
2962+
2963+
// check version
29552964
uint16_t major_version = (0xffff & (superblock.version >> 16));
29562965
uint16_t minor_version = (0xffff & (superblock.version >> 0));
29572966
if ((major_version != LFS_DISK_VERSION_MAJOR ||
@@ -2962,15 +2971,6 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
29622971
goto cleanup;
29632972
}
29642973

2965-
res = lfs_dir_get(lfs, &superdir, 0x7ffff000,
2966-
LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 0, sizeof(lfs->root)),
2967-
&lfs->root);
2968-
if (res < 0) {
2969-
err = res;
2970-
goto cleanup;
2971-
}
2972-
lfs_pair_fromle32(lfs->root);
2973-
29742974
// check superblock configuration
29752975
if (superblock.attr_max) {
29762976
if (superblock.attr_max > lfs->attr_max) {
@@ -3145,16 +3145,11 @@ static int32_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t pair[2],
31453145
lfs_block_t child[2] = {pair[0], pair[1]};
31463146
lfs_pair_tole32(child);
31473147
for (int i = 0; i < 2; i++) {
3148-
// iterate over all directory directory entries
3149-
parent->tail[0] = 0;
3150-
parent->tail[1] = 1;
3151-
while (!lfs_pair_isnull(parent->tail)) {
3152-
int32_t tag = lfs_dir_find(lfs, parent, parent->tail, 0x7fc00fff,
3153-
LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 0, sizeof(child)),
3154-
child);
3155-
if (tag != LFS_ERR_NOENT) {
3156-
return tag;
3157-
}
3148+
int32_t tag = lfs_dir_find(lfs, parent,
3149+
(const lfs_block_t[2]){0, 1}, true, 0x7fc00fff,
3150+
LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 0, sizeof(child)), child);
3151+
if (tag != LFS_ERR_NOENT) {
3152+
return tag;
31583153
}
31593154

31603155
lfs_pair_swap(child);
@@ -3190,6 +3185,7 @@ static int lfs_fs_relocate(lfs_t *lfs,
31903185

31913186
if (tag != LFS_ERR_NOENT) {
31923187
// update disk, this creates a desync
3188+
lfs_global_deorphaned(lfs, false);
31933189
lfs_pair_tole32(newpair);
31943190
int err = lfs_dir_commit(lfs, &parent,
31953191
&(lfs_mattr_t){.tag=tag, .buffer=newpair});

0 commit comments

Comments
 (0)