Skip to content

Commit

Permalink
Cleaned up config options
Browse files Browse the repository at this point in the history
- Updated documentation where needed
- Added asserts which take into account relationships with the new
  cache_size configuration
- Restructured ordering to be consistent for the three main
  configurables: LFS_ATTR_MAX, LFS_NAME_MAX, and LFS_INLINE_MAX
  • Loading branch information
geky committed Oct 16, 2018
1 parent 3cfa086 commit 1941bbd
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 56 deletions.
56 changes: 27 additions & 29 deletions lfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2703,6 +2703,16 @@ static inline void lfs_superblocktole32(lfs_superblock_t *superblock) {
static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
lfs->cfg = cfg;

// check that block size is a multiple of cache size is a multiple
// of prog and read sizes
LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->read_size == 0);
LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->prog_size == 0);
LFS_ASSERT(lfs->cfg->block_size % lfs->cfg->cache_size == 0);

// check that the block size is large enough to fit ctz pointers
LFS_ASSERT(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4))
<= lfs->cfg->block_size);

// setup read cache
lfs->rcache.block = 0xffffffff;
if (lfs->cfg->read_buffer) {
Expand All @@ -2725,7 +2735,7 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
}
}

// setup lookahead, round down to nearest 32-bits
// setup lookahead, must be multiple of 32-bits
LFS_ASSERT(lfs->cfg->lookahead % 32 == 0);
LFS_ASSERT(lfs->cfg->lookahead > 0);
if (lfs->cfg->lookahead_buffer) {
Expand All @@ -2737,22 +2747,12 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
}
}

// check that block size is a multiple of cache size is a multiple
// of prog and read sizes
LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->read_size == 0);
LFS_ASSERT(lfs->cfg->cache_size % lfs->cfg->prog_size == 0);
LFS_ASSERT(lfs->cfg->block_size % lfs->cfg->cache_size == 0);

// check that the block size is large enough to fit ctz pointers
LFS_ASSERT(4*lfs_npw2(0xffffffff / (lfs->cfg->block_size-2*4))
<= lfs->cfg->block_size);

// check that the size limits are sane
LFS_ASSERT(lfs->cfg->inline_size <= LFS_INLINE_MAX);
LFS_ASSERT(lfs->cfg->inline_size <= lfs->cfg->read_size); // TODO
LFS_ASSERT(lfs->cfg->inline_size <= lfs->cfg->cache_size);
lfs->inline_size = lfs->cfg->inline_size;
if (!lfs->inline_size) {
lfs->inline_size = lfs_min(LFS_INLINE_MAX, lfs->cfg->read_size);
lfs->inline_size = lfs_min(LFS_INLINE_MAX, lfs->cfg->cache_size);
}

LFS_ASSERT(lfs->cfg->attr_size <= LFS_ATTR_MAX);
Expand Down Expand Up @@ -2841,9 +2841,9 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {

.block_size = lfs->cfg->block_size,
.block_count = lfs->cfg->block_count,
.inline_size = lfs->inline_size,
.attr_size = lfs->attr_size,
.name_size = lfs->name_size,
.inline_size = lfs->inline_size,
};

lfs_superblocktole32(&superblock);
Expand Down Expand Up @@ -2883,9 +2883,6 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
lfs_mdir_t superdir;
err = lfs_dir_fetch(lfs, &superdir, (const lfs_block_t[2]){0, 1});
if (err) {
if (err == LFS_ERR_CORRUPT) {
LFS_ERROR("Invalid superblock at %d %d", 0, 1);
}
return err;
}

Expand All @@ -2899,8 +2896,8 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
lfs_superblockfromle32(&superblock);

if (memcmp(superblock.magic, "littlefs", 8) != 0) {
LFS_ERROR("Invalid superblock at %d %d", 0, 1);
return LFS_ERR_CORRUPT;
LFS_ERROR("Invalid superblock \"%.8s\"", superblock.magic);
return LFS_ERR_INVAL;
}

uint16_t major_version = (0xffff & (superblock.version >> 16));
Expand All @@ -2919,16 +2916,7 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
}
lfs_pairfromle32(lfs->root);

if (superblock.inline_size) {
if (superblock.inline_size > lfs->inline_size) {
LFS_ERROR("Unsupported inline size (%d > %d)",
superblock.inline_size, lfs->inline_size);
return LFS_ERR_INVAL;
}

lfs->inline_size = superblock.inline_size;
}

// check superblock configuration
if (superblock.attr_size) {
if (superblock.attr_size > lfs->attr_size) {
LFS_ERROR("Unsupported attr size (%d > %d)",
Expand All @@ -2949,6 +2937,16 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
lfs->name_size = superblock.name_size;
}

if (superblock.inline_size) {
if (superblock.inline_size > lfs->inline_size) {
LFS_ERROR("Unsupported inline size (%d > %d)",
superblock.inline_size, lfs->inline_size);
return LFS_ERR_INVAL;
}

lfs->inline_size = superblock.inline_size;
}

// scan for any global updates
lfs_mdir_t dir = {.tail = {0, 1}};
while (!lfs_pairisnull(dir.tail)) {
Expand Down
54 changes: 27 additions & 27 deletions lfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,31 +50,29 @@ typedef int32_t lfs_soff_t;

typedef uint32_t lfs_block_t;

// Maximum inline file size in bytes. Large inline files require a larger
// read and prog cache, but if a file can be inline it does not need its own
// data block. LFS_ATTR_MAX + LFS_INLINE_MAX must be <= 0xffff. Stored in
// superblock and must be respected by other littlefs drivers.
// TODO doc
#ifndef LFS_INLINE_MAX
#define LFS_INLINE_MAX 0xfff
#endif

// Maximum size of all attributes per file in bytes, may be redefined but a
// a smaller LFS_ATTR_MAX has no benefit. LFS_ATTR_MAX + LFS_INLINE_MAX
// must be <= 0xffff. Stored in superblock and must be respected by other
// a smaller LFS_ATTR_MAX has no benefit. Stored in 12-bits and limited
// to <= 0xfff. Stored in superblock and must be respected by other
// littlefs drivers.
// TODO doc
#ifndef LFS_ATTR_MAX
#define LFS_ATTR_MAX 0xfff
#endif

// Max name size in bytes, may be redefined to reduce the size of the
// info struct. Stored in superblock and must be respected by other
// littlefs drivers.
// Maximum name size in bytes, may be redefined to reduce the size of the
// info struct. Limited to <= LFS_ATTR_MAX. Stored in superblock and must
// be respected by other littlefs drivers.
#ifndef LFS_NAME_MAX
#define LFS_NAME_MAX 0xff
#endif

// Maximum inline file size in bytes. Large inline files require a larger
// cache size, but if a file can be inline it does not need its own data
// block. Limited to <= LFS_ATTR_MAX and <= cache_size. Stored in superblock
// and must be respected by other littlefs drivers.
#ifndef LFS_INLINE_MAX
#define LFS_INLINE_MAX 0xfff
#endif

// Possible error codes, these are negative to allow
// valid positive return values
enum lfs_error {
Expand Down Expand Up @@ -110,7 +108,7 @@ enum lfs_type {
LFS_TYPE_TAIL = 0x0c0,
LFS_TYPE_SOFTTAIL = 0x0c0,
LFS_TYPE_HARDTAIL = 0x0c1,
LFS_TYPE_CRC = 0x0f0, // TODO are trailing ones useful?
LFS_TYPE_CRC = 0x0f0,

LFS_TYPE_INLINESTRUCT = 0x040,
LFS_TYPE_CTZSTRUCT = 0x041,
Expand Down Expand Up @@ -216,15 +214,8 @@ struct lfs_config {
// lookahead block.
void *lookahead_buffer;

// Optional upper limit on inlined files in bytes. Large inline files
// require a larger read and prog cache, but if a file can be inlined it
// does not need its own data block. Must be smaller than the read size
// and prog size. Defaults to min(LFS_INLINE_MAX, read_size) when zero.
// Stored in superblock and must be respected by other littlefs drivers.
lfs_size_t inline_size;

// Optional upper limit on attributes per file in bytes. No downside for
// larger attributes size but must be less than LFS_ATTR_MAX. Defaults to
// Optional upper limit on file attributes in bytes. No downside for larger
// attributes size but must be less than LFS_ATTR_MAX. Defaults to
// LFS_ATTR_MAX when zero.Stored in superblock and must be respected by
// other littlefs drivers.
lfs_size_t attr_size;
Expand All @@ -234,6 +225,13 @@ struct lfs_config {
// the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX when zero. Stored in
// superblock and must be respected by other littlefs drivers.
lfs_size_t name_size;

// Optional upper limit on inlined files in bytes. Large inline files
// require a larger cache size, but if a file can be inlined it does not
// need its own data block. Must be smaller than cache_size and less than
// LFS_INLINE_MAX. Defaults to min(LFS_INLINE_MAX, read_size) when zero.
// Stored in superblock and must be respected by other littlefs drivers.
lfs_size_t inline_size;
};

// File info structure
Expand Down Expand Up @@ -355,9 +353,9 @@ typedef struct lfs_superblock {
lfs_size_t block_size;
lfs_size_t block_count;

lfs_size_t inline_size;
lfs_size_t attr_size;
lfs_size_t name_size;
lfs_size_t inline_size;
} lfs_superblock_t;

typedef struct lfs_free {
Expand All @@ -381,9 +379,11 @@ typedef struct lfs {
lfs_free_t free;

const struct lfs_config *cfg;
lfs_size_t inline_size;
lfs_size_t block_size;
lfs_size_t block_count;
lfs_size_t attr_size;
lfs_size_t name_size;
lfs_size_t inline_size;
} lfs_t;


Expand Down

0 comments on commit 1941bbd

Please sign in to comment.