Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 26 additions & 13 deletions lfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -452,14 +452,16 @@ static int lfs_alloc_lookahead(void *p, lfs_block_t block) {
return 0;
}

// indicate allocated blocks have been committed into the filesystem, this
// is to prevent blocks from being garbage collected in the middle of a
// commit operation
static void lfs_alloc_ack(lfs_t *lfs) {
lfs->free.ack = lfs->cfg->block_count;
}

// Invalidate the lookahead buffer. This is done during mounting and
// failed traversals
static void lfs_alloc_reset(lfs_t *lfs) {
lfs->free.off = lfs->seed % lfs->cfg->block_size;
// drop the lookahead buffer, this is done during mounting and failed
// traversals in order to avoid invalid lookahead state
static void lfs_alloc_drop(lfs_t *lfs) {
lfs->free.size = 0;
lfs->free.i = 0;
lfs_alloc_ack(lfs);
Expand Down Expand Up @@ -505,7 +507,7 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) {
memset(lfs->free.buffer, 0, lfs->cfg->lookahead_size);
int err = lfs_fs_traverseraw(lfs, lfs_alloc_lookahead, lfs, true);
if (err) {
lfs_alloc_reset(lfs);
lfs_alloc_drop(lfs);
return err;
}
}
Expand Down Expand Up @@ -870,8 +872,10 @@ static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs,
ptag ^= (lfs_tag_t)(lfs_tag_chunk(tag) & 1U) << 31;

// toss our crc into the filesystem seed for
// pseudorandom numbers
lfs->seed ^= crc;
// pseudorandom numbers, note we use another crc here
// as a collection function because it is sufficiently
// random and convenient
lfs->seed = lfs_crc(lfs->seed, &crc, sizeof(crc));

// update with what's found so far
besttag = tempbesttag;
Expand Down Expand Up @@ -1261,12 +1265,13 @@ static int lfs_dir_commitattr(lfs_t *lfs, struct lfs_commit *commit,
}

static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) {
const lfs_off_t off1 = commit->off;
const uint32_t crc1 = commit->crc;
// align to program units
const lfs_off_t end = lfs_alignup(off1 + 2*sizeof(uint32_t),
const lfs_off_t end = lfs_alignup(commit->off + 2*sizeof(uint32_t),
lfs->cfg->prog_size);

lfs_off_t off1 = 0;
uint32_t crc1 = 0;

// create crc tags to fill up remainder of commit, note that
// padding is not crced, which lets fetches skip padding but
// makes committing a bit more complicated
Expand Down Expand Up @@ -1302,6 +1307,12 @@ static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) {
return err;
}

// keep track of non-padding checksum to verify
if (off1 == 0) {
off1 = commit->off + sizeof(uint32_t);
crc1 = commit->crc;
}

commit->off += sizeof(tag)+lfs_tag_size(tag);
commit->ptag = tag ^ ((lfs_tag_t)reset << 31);
commit->crc = 0xffffffff; // reset crc for next "commit"
Expand All @@ -1315,7 +1326,7 @@ static int lfs_dir_commitcrc(lfs_t *lfs, struct lfs_commit *commit) {

// successful commit, check checksums to make sure
lfs_off_t off = commit->begin;
lfs_off_t noff = off1 + sizeof(uint32_t);
lfs_off_t noff = off1;
while (off < end) {
uint32_t crc = 0xffffffff;
for (lfs_off_t i = off; i < noff+sizeof(uint32_t); i++) {
Expand Down Expand Up @@ -3797,8 +3808,10 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
lfs->gstate.tag += !lfs_tag_isvalid(lfs->gstate.tag);
lfs->gdisk = lfs->gstate;

// setup free lookahead
lfs_alloc_reset(lfs);
// setup free lookahead, to distribute allocations uniformly across
// boots, we start the allocator at a random location
lfs->free.off = lfs->seed % lfs->cfg->block_count;
lfs_alloc_drop(lfs);

LFS_TRACE("lfs_mount -> %d", 0);
return 0;
Expand Down
2 changes: 1 addition & 1 deletion scripts/readtree.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def main(args):
struct.unpack('<HH', superblock[1].data[0:4].ljust(4, b'\xff'))))
print("%-47s%s" % ("littlefs v%s.%s" % version,
"data (truncated, if it fits)"
if not any([args.no_truncate, args.tags, args.log, args.all]) else ""))
if not any([args.no_truncate, args.log, args.all]) else ""))

# print gstate
print("gstate 0x%s" % ''.join('%02x' % c for c in gstate))
Expand Down