Skip to content

Commit 8bc8178

Browse files
committed
WIP Modified CRC valid bit to check all tags
Allows earlier exit when parsing bad blocks
1 parent a326e47 commit 8bc8178

File tree

3 files changed

+27
-22
lines changed

3 files changed

+27
-22
lines changed

lfs.c

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ static inline uint16_t lfs_tag_type(uint32_t tag) {
385385
}
386386

387387
static inline uint16_t lfs_tag_subtype(uint32_t tag) {
388-
return (tag & 0x7c000000) >> 22;
388+
return ((tag & 0x7c000000) >> 26) << 4;
389389
}
390390

391391
static inline uint16_t lfs_tag_id(uint32_t tag) {
@@ -470,7 +470,7 @@ static int32_t lfs_commit_get(lfs_t *lfs, lfs_block_t block, lfs_off_t off,
470470
while (off >= 2*sizeof(tag)+lfs_tag_size(tag)) {
471471
off -= sizeof(tag)+lfs_tag_size(tag);
472472

473-
if (lfs_tag_type(tag) == LFS_TYPE_CRC && stopatcommit) {
473+
if (lfs_tag_subtype(tag) == LFS_TYPE_CRC && stopatcommit) {
474474
break;
475475
} else if (lfs_tag_type(tag) == LFS_TYPE_DELETE) {
476476
if (lfs_tag_id(tag) <= lfs_tag_id(gettag + getdiff)) {
@@ -502,6 +502,7 @@ static int32_t lfs_commit_get(lfs_t *lfs, lfs_block_t block, lfs_off_t off,
502502
return err;
503503
}
504504
tag ^= lfs_fromle32(ntag);
505+
tag &= 0x7fffffff
505506
}
506507

507508
return LFS_ERR_NOENT;
@@ -632,8 +633,7 @@ static int lfs_commit_move(lfs_t *lfs, struct lfs_commit *commit,
632633
return err;
633634
}
634635

635-
ntag = lfs_fromle32(ntag);
636-
ntag ^= tag;
636+
ntag = lfs_fromle32(ntag) ^ tag;
637637
tag |= 0x80000000;
638638
}
639639

@@ -687,7 +687,7 @@ static int lfs_commit_crc(lfs_t *lfs, struct lfs_commit *commit) {
687687
lfs->cfg->prog_size);
688688

689689
// read erased state from next program unit
690-
uint32_t tag = 0;
690+
uint32_t tag;
691691
int err = lfs_bd_read(lfs,
692692
&lfs->pcache, &lfs->rcache, sizeof(tag),
693693
commit->block, off, &tag, sizeof(tag));
@@ -696,10 +696,9 @@ static int lfs_commit_crc(lfs_t *lfs, struct lfs_commit *commit) {
696696
}
697697

698698
// build crc tag
699-
tag = lfs_fromle32(tag);
700-
tag = (0x80000000 & ~tag) |
701-
LFS_MKTAG(LFS_TYPE_CRC, 0x3ff,
702-
off - (commit->off+sizeof(uint32_t)));
699+
bool reset = ~lfs_fromle32(tag) >> 31;
700+
tag = LFS_MKTAG(LFS_TYPE_CRC + reset,
701+
0x3ff, off - (commit->off+sizeof(uint32_t)));
703702

704703
// write out crc
705704
uint32_t footer[2];
@@ -713,7 +712,7 @@ static int lfs_commit_crc(lfs_t *lfs, struct lfs_commit *commit) {
713712
return err;
714713
}
715714
commit->off += sizeof(tag)+lfs_tag_size(tag);
716-
commit->ptag = tag;
715+
commit->ptag = tag ^ (reset << 31);
717716

718717
// flush buffers
719718
err = lfs_bd_sync(lfs, &lfs->pcache, &lfs->rcache, false);
@@ -774,7 +773,7 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir) {
774773

775774
// set defaults
776775
dir->off = sizeof(dir->rev);
777-
dir->etag = 0;
776+
dir->etag = 0xffffffff;
778777
dir->count = 0;
779778
dir->tail[0] = 0xffffffff;
780779
dir->tail[1] = 0xffffffff;
@@ -817,7 +816,7 @@ static int32_t lfs_dir_fetchmatch(lfs_t *lfs,
817816
// load blocks and check crc
818817
for (int i = 0; i < 2; i++) {
819818
lfs_off_t off = sizeof(dir->rev);
820-
uint32_t ptag = 0;
819+
uint32_t ptag = 0xffffffff;
821820
uint32_t crc = 0xffffffff;
822821

823822
dir->rev = lfs_tole32(rev[0]);
@@ -851,8 +850,8 @@ static int32_t lfs_dir_fetchmatch(lfs_t *lfs,
851850
tag = lfs_fromle32(tag) ^ ptag;
852851

853852
// next commit not yet programmed
854-
if (lfs_tag_type(ptag) == LFS_TYPE_CRC && !lfs_tag_isvalid(tag)) {
855-
dir->erased = true;
853+
if (!lfs_tag_isvalid(tag)) {
854+
dir->erased = (lfs_tag_subtype(ptag) == LFS_TYPE_CRC);
856855
break;
857856
}
858857

@@ -862,7 +861,7 @@ static int32_t lfs_dir_fetchmatch(lfs_t *lfs,
862861
break;
863862
}
864863

865-
if (lfs_tag_type(tag) == LFS_TYPE_CRC) {
864+
if (lfs_tag_subtype(tag) == LFS_TYPE_CRC) {
866865
// check the crc attr
867866
uint32_t dcrc;
868867
err = lfs_bd_read(lfs,
@@ -882,6 +881,10 @@ static int32_t lfs_dir_fetchmatch(lfs_t *lfs,
882881
break;
883882
}
884883

884+
// reset the next bit if we need to
885+
tag ^= (lfs_tag_type(tag) & 1) << 31;
886+
887+
// update with what's found so far
885888
foundtag = tempfoundtag;
886889
dir->off = off + sizeof(tag)+lfs_tag_size(tag);
887890
dir->etag = tag;
@@ -1096,7 +1099,7 @@ static int lfs_dir_compact(lfs_t *lfs,
10961099
// setup commit state
10971100
commit.off = 0;
10981101
commit.crc = 0xffffffff;
1099-
commit.ptag = 0;
1102+
commit.ptag = 0xffffffff;
11001103

11011104
// space is complicated, we need room for tail, crc, globals,
11021105
// cleanup delete, and we cap at half a block to give room

tests/corrupt.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def corrupt(block):
1111
file.read(4)
1212

1313
# go to last commit
14-
tag = 0
14+
tag = 0xffffffff
1515
while True:
1616
try:
1717
ntag, = struct.unpack('<I', file.read(4))

tests/debug.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
(0x1f0, 0x080): 'globals',
1313
(0x1ff, 0x0c0): 'tail soft',
1414
(0x1ff, 0x0c1): 'tail hard',
15-
(0x1ff, 0x0f0): 'crc',
15+
(0x1f0, 0x0f0): 'crc',
1616
(0x1ff, 0x040): 'struct dir',
1717
(0x1ff, 0x041): 'struct inline',
1818
(0x1ff, 0x042): 'struct ctz',
@@ -63,7 +63,7 @@ def main(*blocks):
6363
print "%-4s %-8s %-14s %3s %3s %s" % (
6464
'off', 'tag', 'type', 'id', 'len', 'dump')
6565

66-
tag = 0
66+
tag = 0xffffffff
6767
off = 4
6868
while True:
6969
try:
@@ -79,23 +79,25 @@ def main(*blocks):
7979
type = (tag & 0x7fc00000) >> 22
8080
id = (tag & 0x003ff000) >> 12
8181
size = (tag & 0x00000fff) >> 0
82+
iscrc = (type & 0x1f0) == 0x0f0
8283

8384
data = file.read(size)
84-
if type == 0x0f0:
85+
if iscrc:
8586
crc = binascii.crc32(data[:4], crc)
8687
else:
8788
crc = binascii.crc32(data, crc)
8889

8990
print '%04x: %08x %-14s %3s %3d %-23s %-8s' % (
9091
off, tag,
91-
typeof(type) + (' bad!' if type == 0x0f0 and ~crc else ''),
92+
typeof(type) + (' bad!' if iscrc and ~crc else ''),
9293
id if id != 0x3ff else '.', size,
9394
' '.join('%02x' % ord(c) for c in data[:8]),
9495
''.join(c if c >= ' ' and c <= '~' else '.' for c in data[:8]))
9596

9697
off += tag & 0xfff
97-
if type == 0x0f0:
98+
if iscrc:
9899
crc = 0
100+
tag ^= (type & 1) << 31
99101

100102
return 0
101103

0 commit comments

Comments
 (0)