Skip to content

Commit d7e4aba

Browse files
committed
Edited tag structure to balance size vs id count
This is a minor tweak that resulted from looking at some other use cases for the littlefs data-structure on disk. Consider an implementation that does not need to buffer inline-files in RAM. In this case we should have as large a tag size field as possible. Unfortunately, we don't have much space to work with in the 32-bit tag struct, so we have to make some compromises. These limitations could be removed with a 64-bit tag struct, at the cost of code size. 32-bit tag structure: [--- 32 ---] [1|- 9 -|- 9 -|-- 13 --] ^ ^ ^ ^- entry length | | \-------- file id | \-------------- tag type \------------------ valid bit
1 parent cafe6ab commit d7e4aba

File tree

4 files changed

+45
-45
lines changed

4 files changed

+45
-45
lines changed

lfs.c

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ typedef uint32_t lfs_tag_t;
265265
typedef int32_t lfs_stag_t;
266266

267267
#define LFS_MKTAG(type, id, size) \
268-
(((lfs_tag_t)(type) << 22) | ((lfs_tag_t)(id) << 12) | (lfs_tag_t)(size))
268+
(((lfs_tag_t)(type) << 22) | ((lfs_tag_t)(id) << 13) | (lfs_tag_t)(size))
269269

270270
static inline bool lfs_tag_isvalid(lfs_tag_t tag) {
271271
return !(tag & 0x80000000);
@@ -276,7 +276,7 @@ static inline bool lfs_tag_isuser(lfs_tag_t tag) {
276276
}
277277

278278
static inline bool lfs_tag_isdelete(lfs_tag_t tag) {
279-
return (tag & 0x00000fff) == 0xfff;
279+
return ((int32_t)(tag << 19) >> 19) == -1;
280280
}
281281

282282
static inline uint16_t lfs_tag_type(lfs_tag_t tag) {
@@ -288,11 +288,11 @@ static inline uint16_t lfs_tag_subtype(lfs_tag_t tag) {
288288
}
289289

290290
static inline uint16_t lfs_tag_id(lfs_tag_t tag) {
291-
return (tag & 0x003ff000) >> 12;
291+
return (tag & 0x003fe000) >> 13;
292292
}
293293

294294
static inline lfs_size_t lfs_tag_size(lfs_tag_t tag) {
295-
return tag & 0x00000fff;
295+
return tag & 0x00001fff;
296296
}
297297

298298
static inline lfs_size_t lfs_tag_dsize(lfs_tag_t tag) {
@@ -837,14 +837,14 @@ static int lfs_dir_getglobals(lfs_t *lfs, const lfs_mdir_t *dir,
837837

838838
static int lfs_dir_getinfo(lfs_t *lfs, lfs_mdir_t *dir,
839839
uint16_t id, struct lfs_info *info) {
840-
if (id == 0x3ff) {
840+
if (id == 0x1ff) {
841841
// special case for root
842842
strcpy(info->name, "/");
843843
info->type = LFS_TYPE_DIR;
844844
return 0;
845845
}
846846

847-
lfs_stag_t tag = lfs_dir_get(lfs, dir, 0x7c3ff000,
847+
lfs_stag_t tag = lfs_dir_get(lfs, dir, 0x7c3fe000,
848848
LFS_MKTAG(LFS_TYPE_NAME, id, lfs->name_max+1), info->name);
849849
if (tag < 0) {
850850
return tag;
@@ -853,7 +853,7 @@ static int lfs_dir_getinfo(lfs_t *lfs, lfs_mdir_t *dir,
853853
info->type = lfs_tag_type(tag);
854854

855855
struct lfs_ctz ctz;
856-
tag = lfs_dir_get(lfs, dir, 0x7c3ff000,
856+
tag = lfs_dir_get(lfs, dir, 0x7c3fe000,
857857
LFS_MKTAG(LFS_TYPE_STRUCT, id, sizeof(ctz)), &ctz);
858858
if (tag < 0) {
859859
return tag;
@@ -912,7 +912,7 @@ static lfs_stag_t lfs_dir_find(lfs_t *lfs,
912912
*path = NULL;
913913

914914
// default to root dir
915-
lfs_stag_t tag = LFS_MKTAG(LFS_TYPE_DIR, 0x3ff, 0);
915+
lfs_stag_t tag = LFS_MKTAG(LFS_TYPE_DIR, 0x1ff, 0);
916916
lfs_block_t pair[2] = {lfs->root[0], lfs->root[1]};
917917

918918
while (true) {
@@ -968,8 +968,8 @@ static lfs_stag_t lfs_dir_find(lfs_t *lfs,
968968
}
969969

970970
// grab the entry data
971-
if (lfs_tag_id(tag) != 0x3ff) {
972-
lfs_stag_t res = lfs_dir_get(lfs, dir, 0x7c3ff000,
971+
if (lfs_tag_id(tag) != 0x1ff) {
972+
lfs_stag_t res = lfs_dir_get(lfs, dir, 0x7c3fe000,
973973
LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tag_id(tag), 8), pair);
974974
if (res < 0) {
975975
return res;
@@ -978,7 +978,7 @@ static lfs_stag_t lfs_dir_find(lfs_t *lfs,
978978
}
979979

980980
// find entry matching name
981-
tag = lfs_dir_findmatch(lfs, dir, pair, false, 0x7c000fff,
981+
tag = lfs_dir_findmatch(lfs, dir, pair, false, 0x7c001fff,
982982
LFS_MKTAG(LFS_TYPE_NAME, 0, namelen),
983983
lfs_dir_find_match, &(struct lfs_dir_find_match){
984984
lfs, name, namelen});
@@ -1046,7 +1046,7 @@ static int lfs_commit_move_match(void *data,
10461046
.pair[0] = commit->block,
10471047
.off = commit->off,
10481048
.etag = commit->ptag}, NULL,
1049-
lfs_tag_isuser(tag) ? 0x7ffff000 : 0x7c3ff000, tag, 0,
1049+
lfs_tag_isuser(tag) ? 0x7fffe000 : 0x7c3fe000, tag, 0,
10501050
lfs_dir_get_match, &(struct lfs_dir_get_match){
10511051
lfs, NULL, 0, true});
10521052
if (res < 0 && res != LFS_ERR_NOENT) {
@@ -1089,7 +1089,7 @@ static int lfs_commit_attr(lfs_t *lfs, struct lfs_commit *commit,
10891089
if (lfs_tag_type(tag) == LFS_FROM_MOVE) {
10901090
// special case for moves
10911091
return lfs_commit_move(lfs, commit, 1,
1092-
0x003ff000, LFS_MKTAG(0, lfs_tag_size(tag), 0),
1092+
0x003fe000, LFS_MKTAG(0, lfs_tag_size(tag), 0),
10931093
LFS_MKTAG(0, lfs_tag_id(tag), 0) -
10941094
LFS_MKTAG(0, lfs_tag_size(tag), 0),
10951095
buffer, NULL);
@@ -1146,7 +1146,7 @@ static int lfs_commit_globals(lfs_t *lfs, struct lfs_commit *commit,
11461146
struct lfs_globals *globals) {
11471147
return lfs_commit_attr(lfs, commit,
11481148
LFS_MKTAG(LFS_TYPE_GLOBALS + 2*globals->hasmove + globals->orphans,
1149-
0x3ff, 10), globals);
1149+
0x1ff, 10), globals);
11501150
}
11511151

11521152
static int lfs_commit_crc(lfs_t *lfs, struct lfs_commit *commit,
@@ -1166,8 +1166,8 @@ static int lfs_commit_crc(lfs_t *lfs, struct lfs_commit *commit,
11661166

11671167
// build crc tag
11681168
bool reset = ~lfs_fromle32(tag) >> 31;
1169-
tag = LFS_MKTAG(LFS_TYPE_CRC + (compacting << 1) + reset,
1170-
0x3ff, off - (commit->off+sizeof(lfs_tag_t)));
1169+
tag = LFS_MKTAG(LFS_TYPE_CRC + 2*compacting + reset,
1170+
0x1ff, off - (commit->off+sizeof(lfs_tag_t)));
11711171

11721172
// write out crc
11731173
uint32_t footer[2];
@@ -1267,7 +1267,7 @@ static int lfs_dir_drop(lfs_t *lfs, lfs_mdir_t *dir, const lfs_mdir_t *tail) {
12671267
// update pred's tail
12681268
return lfs_dir_commit(lfs, dir,
12691269
LFS_MKATTR(LFS_TYPE_TAIL + dir->split,
1270-
0x3ff, dir->tail, sizeof(dir->tail),
1270+
0x1ff, dir->tail, sizeof(dir->tail),
12711271
NULL));
12721272
}
12731273

@@ -1369,7 +1369,7 @@ static int lfs_dir_compact(lfs_t *lfs,
13691369
for (uint16_t id = begin; id < end || commit.off < commit.ack; id++) {
13701370
for (int pass = 0; pass < 2; pass++) {
13711371
err = lfs_commit_move(lfs, &commit, pass,
1372-
0x003ff000, LFS_MKTAG(0, id, 0),
1372+
0x003fe000, LFS_MKTAG(0, id, 0),
13731373
-LFS_MKTAG(0, begin, 0),
13741374
source, attrs);
13751375
if (err && !(splitted && !overcompacting &&
@@ -1419,7 +1419,7 @@ static int lfs_dir_compact(lfs_t *lfs,
14191419
lfs_pair_tole32(dir->tail);
14201420
err = lfs_commit_attr(lfs, &commit,
14211421
LFS_MKTAG(LFS_TYPE_TAIL + dir->split,
1422-
0x3ff, sizeof(dir->tail)), dir->tail);
1422+
0x1ff, sizeof(dir->tail)), dir->tail);
14231423
lfs_pair_fromle32(dir->tail);
14241424
if (err) {
14251425
if (err == LFS_ERR_CORRUPT) {
@@ -1737,7 +1737,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) {
17371737
cwd.tail[1] = dir.pair[1];
17381738
lfs_pair_tole32(dir.pair);
17391739
err = lfs_dir_commit(lfs, &cwd,
1740-
LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x3ff, cwd.tail, sizeof(cwd.tail),
1740+
LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x1ff, cwd.tail, sizeof(cwd.tail),
17411741
LFS_MKATTR(LFS_TYPE_DIRSTRUCT, id, dir.pair, sizeof(dir.pair),
17421742
LFS_MKATTR(LFS_TYPE_DIR, id, path, nlen,
17431743
NULL))));
@@ -1760,13 +1760,13 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) {
17601760
}
17611761

17621762
lfs_block_t pair[2];
1763-
if (lfs_tag_id(tag) == 0x3ff) {
1763+
if (lfs_tag_id(tag) == 0x1ff) {
17641764
// handle root dir separately
17651765
pair[0] = lfs->root[0];
17661766
pair[1] = lfs->root[1];
17671767
} else {
17681768
// get dir pair from parent
1769-
lfs_stag_t res = lfs_dir_get(lfs, &dir->m, 0x7c3ff000,
1769+
lfs_stag_t res = lfs_dir_get(lfs, &dir->m, 0x7c3fe000,
17701770
LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tag_id(tag), 8), pair);
17711771
if (res < 0) {
17721772
return res;
@@ -2163,7 +2163,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
21632163
file->flags |= LFS_F_DIRTY;
21642164
} else {
21652165
// try to load what's on disk, if it's inlined we'll fix it later
2166-
tag = lfs_dir_get(lfs, &file->m, 0x7c3ff000,
2166+
tag = lfs_dir_get(lfs, &file->m, 0x7c3fe000,
21672167
LFS_MKTAG(LFS_TYPE_STRUCT, file->id, 8), &file->ctz);
21682168
if (tag < 0) {
21692169
err = tag;
@@ -2175,7 +2175,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
21752175
// fetch attrs
21762176
for (const struct lfs_attr *a = file->cfg->attrs; a; a = a->next) {
21772177
if ((file->flags & 3) != LFS_O_WRONLY) {
2178-
lfs_stag_t res = lfs_dir_get(lfs, &file->m, 0x7ffff000,
2178+
lfs_stag_t res = lfs_dir_get(lfs, &file->m, 0x7fffe000,
21792179
LFS_MKTAG(0x100 | a->type, file->id, a->size), a->buffer);
21802180
if (res < 0 && res != LFS_ERR_NOENT) {
21812181
err = res;
@@ -2218,7 +2218,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
22182218

22192219
// don't always read (may be new/trunc file)
22202220
if (file->ctz.size > 0) {
2221-
lfs_stag_t res = lfs_dir_get(lfs, &file->m, 0x7c3ff000,
2221+
lfs_stag_t res = lfs_dir_get(lfs, &file->m, 0x7c3fe000,
22222222
LFS_MKTAG(LFS_TYPE_STRUCT, file->id, file->ctz.size),
22232223
file->cache.buffer);
22242224
if (res < 0) {
@@ -2778,7 +2778,7 @@ int lfs_remove(lfs_t *lfs, const char *path) {
27782778
if (lfs_tag_type(tag) == LFS_TYPE_DIR) {
27792779
// must be empty before removal
27802780
lfs_block_t pair[2];
2781-
lfs_stag_t res = lfs_dir_get(lfs, &cwd, 0x7c3ff000,
2781+
lfs_stag_t res = lfs_dir_get(lfs, &cwd, 0x7c3fe000,
27822782
LFS_MKTAG(LFS_TYPE_STRUCT, lfs_tag_id(tag), 8), pair);
27832783
if (res < 0) {
27842784
return res;
@@ -2862,7 +2862,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) {
28622862
} else if (lfs_tag_type(prevtag) == LFS_TYPE_DIR) {
28632863
// must be empty before removal
28642864
lfs_block_t prevpair[2];
2865-
lfs_stag_t res = lfs_dir_get(lfs, &newcwd, 0x7c3ff000,
2865+
lfs_stag_t res = lfs_dir_get(lfs, &newcwd, 0x7c3fe000,
28662866
LFS_MKTAG(LFS_TYPE_STRUCT, newid, 8), prevpair);
28672867
if (res < 0) {
28682868
return res;
@@ -2933,7 +2933,7 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
29332933
}
29342934

29352935
uint16_t id = lfs_tag_id(res);
2936-
if (id == 0x3ff) {
2936+
if (id == 0x1ff) {
29372937
// special case for root
29382938
id = 0;
29392939
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
@@ -2942,7 +2942,7 @@ lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
29422942
}
29432943
}
29442944

2945-
res = lfs_dir_get(lfs, &cwd, 0x7ffff000,
2945+
res = lfs_dir_get(lfs, &cwd, 0x7fffe000,
29462946
LFS_MKTAG(0x100 | type, id, lfs_min(size, lfs->attr_max)),
29472947
buffer);
29482948
if (res < 0) {
@@ -2964,7 +2964,7 @@ static int lfs_commitattr(lfs_t *lfs, const char *path,
29642964
}
29652965

29662966
uint16_t id = lfs_tag_id(res);
2967-
if (id == 0x3ff) {
2967+
if (id == 0x1ff) {
29682968
// special case for root
29692969
id = 0;
29702970
int err = lfs_dir_fetch(lfs, &cwd, lfs->root);
@@ -2988,7 +2988,7 @@ int lfs_setattr(lfs_t *lfs, const char *path,
29882988
}
29892989

29902990
int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type) {
2991-
return lfs_commitattr(lfs, path, type, NULL, LFS_ATTR_MAX+1);
2991+
return lfs_commitattr(lfs, path, type, NULL, 0x1fff);
29922992
}
29932993

29942994

@@ -3290,7 +3290,7 @@ int lfs_fs_traverse(lfs_t *lfs,
32903290

32913291
for (uint16_t id = 0; id < dir.count; id++) {
32923292
struct lfs_ctz ctz;
3293-
lfs_stag_t tag = lfs_dir_get(lfs, &dir, 0x7c3ff000,
3293+
lfs_stag_t tag = lfs_dir_get(lfs, &dir, 0x7c3fe000,
32943294
LFS_MKTAG(LFS_TYPE_STRUCT, id, sizeof(ctz)), &ctz);
32953295
if (tag < 0) {
32963296
if (tag == LFS_ERR_NOENT) {
@@ -3393,7 +3393,7 @@ static lfs_stag_t lfs_fs_parent(lfs_t *lfs, const lfs_block_t pair[2],
33933393
for (int i = 0; i < 2; i++) {
33943394
struct lfs_fs_parent_match match = {lfs, {pair[0], pair[1]}};
33953395
lfs_stag_t tag = lfs_dir_findmatch(lfs, parent,
3396-
(const lfs_block_t[2]){0, 1}, true, 0x7fc00fff,
3396+
(const lfs_block_t[2]){0, 1}, true, 0x7fc01fff,
33973397
LFS_MKTAG(LFS_TYPE_DIRSTRUCT, 0, 8),
33983398
lfs_fs_parent_match, &match);
33993399
if (tag != LFS_ERR_NOENT) {
@@ -3458,7 +3458,7 @@ static int lfs_fs_relocate(lfs_t *lfs,
34583458
parent.tail[1] = newpair[1];
34593459
err = lfs_dir_commit(lfs, &parent,
34603460
LFS_MKATTR(LFS_TYPE_TAIL + parent.split,
3461-
0x3ff, parent.tail, sizeof(parent.tail),
3461+
0x1ff, parent.tail, sizeof(parent.tail),
34623462
NULL));
34633463
if (err) {
34643464
return err;
@@ -3532,7 +3532,7 @@ static int lfs_fs_deorphan(lfs_t *lfs) {
35323532
}
35333533

35343534
lfs_block_t pair[2];
3535-
lfs_stag_t res = lfs_dir_get(lfs, &parent, 0x7ffff000, tag, pair);
3535+
lfs_stag_t res = lfs_dir_get(lfs, &parent, 0x7fffe000, tag, pair);
35363536
if (res < 0) {
35373537
return res;
35383538
}
@@ -3547,7 +3547,7 @@ static int lfs_fs_deorphan(lfs_t *lfs) {
35473547
pdir.tail[1] = pair[1];
35483548
err = lfs_dir_commit(lfs, &pdir,
35493549
LFS_MKATTR(LFS_TYPE_SOFTTAIL,
3550-
0x3ff, pdir.tail, sizeof(pdir.tail),
3550+
0x1ff, pdir.tail, sizeof(pdir.tail),
35513551
NULL));
35523552
if (err) {
35533553
return err;

lfs.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ typedef uint32_t lfs_block_t;
4949
// to <= 0xfff. Stored in superblock and must be respected by other
5050
// littlefs drivers.
5151
#ifndef LFS_ATTR_MAX
52-
#define LFS_ATTR_MAX 0xffe
52+
#define LFS_ATTR_MAX 0x1ffe
5353
#endif
5454

5555
// Maximum name size in bytes, may be redefined to reduce the size of the
@@ -64,7 +64,7 @@ typedef uint32_t lfs_block_t;
6464
// block. Limited to <= LFS_ATTR_MAX and <= cache_size. Stored in superblock
6565
// and must be respected by other littlefs drivers.
6666
#ifndef LFS_INLINE_MAX
67-
#define LFS_INLINE_MAX 0xffe
67+
#define LFS_INLINE_MAX 0x1ffe
6868
#endif
6969

7070
// Possible error codes, these are negative to allow

tests/corrupt.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def corrupt(block):
1919
break
2020

2121
tag ^= ntag
22-
size = (tag & 0xfff) if (tag & 0xfff) != 0xfff else 0
22+
size = (tag & 0x1fff) if (tag & 0x1fff) != 0x1fff else 0
2323
file.seek(size, os.SEEK_CUR)
2424

2525
# lob off last 3 bytes

tests/debug.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ def main(*blocks):
7676
off += 4
7777

7878
type = (tag & 0x7fc00000) >> 22
79-
id = (tag & 0x003ff000) >> 12
80-
size = (tag & 0x00000fff) >> 0
79+
id = (tag & 0x003fe000) >> 13
80+
size = (tag & 0x00001fff) >> 0
8181
iscrc = (type & 0x1f0) == 0x0f0
8282

83-
data = file.read(size if size != 0xfff else 0)
83+
data = file.read(size if size != 0x1fff else 0)
8484
if iscrc:
8585
crc = binascii.crc32(data[:4], crc)
8686
else:
@@ -89,12 +89,12 @@ def main(*blocks):
8989
print '%04x: %08x %-14s %3s %3s %-23s %-8s' % (
9090
off, tag,
9191
typeof(type) + (' bad!' if iscrc and ~crc else ''),
92-
id if id != 0x3ff else '.',
93-
size if size != 0xfff else 'x',
92+
id if id != 0x1ff else '.',
93+
size if size != 0x1fff else 'x',
9494
' '.join('%02x' % ord(c) for c in data[:8]),
9595
''.join(c if c >= ' ' and c <= '~' else '.' for c in data[:8]))
9696

97-
off += size if size != 0xfff else 0
97+
off += size if size != 0x1fff else 0
9898
if iscrc:
9999
crc = 0
100100
tag ^= (type & 1) << 31

0 commit comments

Comments
 (0)