Skip to content

Commit

Permalink
Changed how we write out superblock to use append
Browse files Browse the repository at this point in the history
Making the superblock look like "just another entry" allows us to treat
the superblock like "just another entry" and reuse a decent amount of
logic that would otherwise only be used a format and mount time. In this
case we can use append to write out the superblock like it was creating
a new entry on the filesystem.
  • Loading branch information
geky committed Oct 10, 2018
1 parent 701e4fa commit d0e0453
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 52 deletions.
77 changes: 43 additions & 34 deletions lfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2372,38 +2372,40 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {

lfs->root[0] = root.pair[0];
lfs->root[1] = root.pair[1];
superdir.d.tail[0] = lfs->root[0];
superdir.d.tail[1] = lfs->root[1];

// write superblocks
lfs_superblock_t superblock = {
.d.type = LFS_STRUCT_DIR | LFS_TYPE_SUPERBLOCK,
.d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4,
.d.nlen = sizeof(superblock.d.magic),
.d.version = LFS_DISK_VERSION,
.d.magic = {"littlefs"},
.d.block_size = lfs->cfg->block_size,
.d.block_count = lfs->cfg->block_count,
.d.root = {lfs->root[0], lfs->root[1]},
};
superdir.d.tail[0] = root.pair[0];
superdir.d.tail[1] = root.pair[1];
superdir.d.size = sizeof(superdir.d) + sizeof(superblock.d) + 4;

// write both pairs to be safe
// write one superblocks
lfs_superblock_t superblock;
superblock.d.version = LFS_DISK_VERSION,
superblock.d.root[0] = lfs->root[0];
superblock.d.root[1] = lfs->root[1];
superblock.d.block_size = lfs->cfg->block_size;
superblock.d.block_count = lfs->cfg->block_count;

lfs_entry_t superentry;
superentry.d.type = LFS_STRUCT_DIR | LFS_TYPE_SUPERBLOCK;
superentry.d.elen = sizeof(superblock.d);
superentry.d.alen = 0;
superentry.d.nlen = strlen("littlefs");
superentry.off = sizeof(superdir.d);
superentry.size = 4 + superentry.d.elen +
superentry.d.alen + superentry.d.nlen;

lfs_entry_tole32(&superentry.d);
lfs_superblock_tole32(&superblock.d);
bool valid = false;
for (int i = 0; i < 2; i++) {
err = lfs_dir_commit(lfs, &superdir, &(struct lfs_region){
sizeof(superdir.d), 0,
lfs_commit_mem, &superblock.d, sizeof(superblock.d)});
if (err && err != LFS_ERR_CORRUPT) {
return err;
}

valid = valid || !err;
}

if (!valid) {
return LFS_ERR_CORRUPT;
err = lfs_dir_append(lfs, &superdir, &superentry,
&(struct lfs_region){
0, +4,
lfs_commit_mem, &superentry.d, 4,
&(struct lfs_region){
0, +sizeof(superblock.d),
lfs_commit_mem, &superblock.d, sizeof(superblock.d),
&(struct lfs_region){
0, +superentry.d.nlen,
lfs_commit_mem, "littlefs", superentry.d.nlen}}});
if (err) {
return err;
}

// sanity check that fetch works
Expand All @@ -2412,7 +2414,6 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
return err;
}

lfs_alloc_ack(lfs);
return lfs_deinit(lfs);
}

Expand All @@ -2431,25 +2432,33 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
// load superblock
lfs_dir_t dir;
lfs_superblock_t superblock;
char magic[8];
err = lfs_dir_fetch(lfs, &dir, (const lfs_block_t[2]){0, 1});
if (err && err != LFS_ERR_CORRUPT) {
return err;
}

if (!err) {
err = lfs_bd_read(lfs, dir.pair[0], sizeof(dir.d),
err = lfs_bd_read(lfs, dir.pair[0], sizeof(dir.d)+4,
&superblock.d, sizeof(superblock.d));
lfs_superblock_fromle32(&superblock.d);
if (err) {
return err;
}

err = lfs_bd_read(lfs, dir.pair[0],
sizeof(dir.d) + 4 + sizeof(superblock.d),
magic, sizeof(magic));
if (err) {
return err;
}

lfs->root[0] = superblock.d.root[0];
lfs->root[1] = superblock.d.root[1];
}

if (err || memcmp(superblock.d.magic, "littlefs", 8) != 0) {
LFS_ERROR("Invalid superblock at %d %d", 0, 1);
if (err || memcmp(magic, "littlefs", 8) != 0) {
LFS_ERROR("Invalid superblock at %d %d", dir.pair[0], dir.pair[1]);
return LFS_ERR_CORRUPT;
}

Expand Down
5 changes: 0 additions & 5 deletions lfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,15 +257,10 @@ typedef struct lfs_dir {

typedef struct lfs_superblock {
struct lfs_disk_superblock {
uint8_t type;
uint8_t elen;
uint8_t alen;
uint8_t nlen;
lfs_block_t root[2];
uint32_t block_size;
uint32_t block_count;
uint32_t version;
char magic[8];
} d;
} lfs_superblock_t;

Expand Down
4 changes: 2 additions & 2 deletions tests/test_corrupt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ lfs_mktree
lfs_chktree

echo "--- Block corruption ---"
for i in {0..33}
for i in {2..33}
do
rm -rf blocks
mkdir blocks
Expand All @@ -83,7 +83,7 @@ do
done

echo "--- Block persistance ---"
for i in {0..33}
for i in {2..33}
do
rm -rf blocks
mkdir blocks
Expand Down
12 changes: 1 addition & 11 deletions tests/test_format.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,10 @@ echo "--- Invalid mount ---"
tests/test.py << TEST
lfs_format(&lfs, &cfg) => 0;
TEST
rm blocks/0 blocks/1
rm -f blocks/0 blocks/1
tests/test.py << TEST
lfs_mount(&lfs, &cfg) => LFS_ERR_CORRUPT;
TEST

echo "--- Valid corrupt mount ---"
tests/test.py << TEST
lfs_format(&lfs, &cfg) => 0;
TEST
rm blocks/0
tests/test.py << TEST
lfs_mount(&lfs, &cfg) => 0;
lfs_unmount(&lfs) => 0;
TEST

echo "--- Results ---"
tests/stats.py

0 comments on commit d0e0453

Please sign in to comment.