Changed attr_max to be specific to custom attributes

While technically, both system and user attributes share the same disk
limitations, that's not what attr_max represents when considered from
the user's perspective. To the user, attr_max applies only to custom
attributes. This means attr_max should not impact other configurable
limitations, such as inline files, and the ordering should be
reconsidered with what the user finds most important.
This commit is contained in:
Christopher Haster
2018-10-02 18:28:37 -05:00
parent f010d2add1
commit ad96fca18f
2 changed files with 53 additions and 49 deletions

41
lfs.c
View File

@@ -388,18 +388,18 @@ static inline void lfs_superblock_fromle32(lfs_superblock_t *superblock) {
superblock->version = lfs_fromle32(superblock->version); superblock->version = lfs_fromle32(superblock->version);
superblock->block_size = lfs_fromle32(superblock->block_size); superblock->block_size = lfs_fromle32(superblock->block_size);
superblock->block_count = lfs_fromle32(superblock->block_count); superblock->block_count = lfs_fromle32(superblock->block_count);
superblock->name_max = lfs_fromle32(superblock->name_max);
superblock->inline_max = lfs_fromle32(superblock->inline_max); superblock->inline_max = lfs_fromle32(superblock->inline_max);
superblock->attr_max = lfs_fromle32(superblock->attr_max); superblock->attr_max = lfs_fromle32(superblock->attr_max);
superblock->name_max = lfs_fromle32(superblock->name_max);
} }
static inline void lfs_superblock_tole32(lfs_superblock_t *superblock) { static inline void lfs_superblock_tole32(lfs_superblock_t *superblock) {
superblock->version = lfs_tole32(superblock->version); superblock->version = lfs_tole32(superblock->version);
superblock->block_size = lfs_tole32(superblock->block_size); superblock->block_size = lfs_tole32(superblock->block_size);
superblock->block_count = lfs_tole32(superblock->block_count); superblock->block_count = lfs_tole32(superblock->block_count);
superblock->name_max = lfs_tole32(superblock->name_max);
superblock->inline_max = lfs_tole32(superblock->inline_max); superblock->inline_max = lfs_tole32(superblock->inline_max);
superblock->attr_max = lfs_tole32(superblock->attr_max); superblock->attr_max = lfs_tole32(superblock->attr_max);
superblock->name_max = lfs_tole32(superblock->name_max);
} }
@@ -3054,6 +3054,12 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
} }
// check that the size limits are sane // check that the size limits are sane
LFS_ASSERT(lfs->cfg->name_max <= LFS_NAME_MAX);
lfs->name_max = lfs->cfg->name_max;
if (!lfs->name_max) {
lfs->name_max = LFS_NAME_MAX;
}
LFS_ASSERT(lfs->cfg->inline_max <= LFS_INLINE_MAX); LFS_ASSERT(lfs->cfg->inline_max <= LFS_INLINE_MAX);
LFS_ASSERT(lfs->cfg->inline_max <= lfs->cfg->cache_size); LFS_ASSERT(lfs->cfg->inline_max <= lfs->cfg->cache_size);
lfs->inline_max = lfs->cfg->inline_max; lfs->inline_max = lfs->cfg->inline_max;
@@ -3067,12 +3073,6 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
lfs->attr_max = LFS_ATTR_MAX; lfs->attr_max = LFS_ATTR_MAX;
} }
LFS_ASSERT(lfs->cfg->name_max <= LFS_NAME_MAX);
lfs->name_max = lfs->cfg->name_max;
if (!lfs->name_max) {
lfs->name_max = LFS_NAME_MAX;
}
// setup default state // setup default state
lfs->root[0] = 0xffffffff; lfs->root[0] = 0xffffffff;
lfs->root[1] = 0xffffffff; lfs->root[1] = 0xffffffff;
@@ -3132,9 +3132,9 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
.block_size = lfs->cfg->block_size, .block_size = lfs->cfg->block_size,
.block_count = lfs->cfg->block_count, .block_count = lfs->cfg->block_count,
.attr_max = lfs->attr_max,
.name_max = lfs->name_max, .name_max = lfs->name_max,
.inline_max = lfs->inline_max, .inline_max = lfs->inline_max,
.attr_max = lfs->attr_max,
}; };
lfs_superblock_tole32(&superblock); lfs_superblock_tole32(&superblock);
@@ -3204,17 +3204,6 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
} }
// check superblock configuration // check superblock configuration
if (superblock.attr_max) {
if (superblock.attr_max > lfs->attr_max) {
LFS_ERROR("Unsupported attr_max (%"PRIu32" > %"PRIu32")",
superblock.attr_max, lfs->attr_max);
err = LFS_ERR_INVAL;
goto cleanup;
}
lfs->attr_max = superblock.attr_max;
}
if (superblock.name_max) { if (superblock.name_max) {
if (superblock.name_max > lfs->name_max) { if (superblock.name_max > lfs->name_max) {
LFS_ERROR("Unsupported name_max (%"PRIu32" > %"PRIu32")", LFS_ERROR("Unsupported name_max (%"PRIu32" > %"PRIu32")",
@@ -3236,6 +3225,18 @@ int lfs_mount(lfs_t *lfs, const struct lfs_config *cfg) {
lfs->inline_max = superblock.inline_max; lfs->inline_max = superblock.inline_max;
} }
if (superblock.attr_max) {
if (superblock.attr_max > lfs->attr_max) {
LFS_ERROR("Unsupported attr_max (%"PRIu32" > %"PRIu32")",
superblock.attr_max, lfs->attr_max);
err = LFS_ERR_INVAL;
goto cleanup;
}
lfs->attr_max = superblock.attr_max;
}
} }
// has globals? // has globals?

61
lfs.h
View File

@@ -44,29 +44,28 @@ typedef int32_t lfs_soff_t;
typedef uint32_t lfs_block_t; typedef uint32_t lfs_block_t;
// Maximum size of all attributes per file in bytes, may be redefined but a
// 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.
#ifndef LFS_ATTR_MAX
#define LFS_ATTR_MAX 0x1ffe
#endif
// Maximum name size in bytes, may be redefined to reduce the size of the // 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 // info struct. Limited to <= 8190. Stored in superblock and must be
// be respected by other littlefs drivers. // respected by other littlefs drivers.
#ifndef LFS_NAME_MAX #ifndef LFS_NAME_MAX
#define LFS_NAME_MAX 0xff #define LFS_NAME_MAX 0xff
#endif #endif
// Maximum inline file size in bytes. Large inline files require a larger // Maximum inline file size in bytes, may be redefined to limit RAM usage,
// cache size, but if a file can be inline it does not need its own data // but littlefs will automatically limit the LFS_INLINE_MAX to the
// block. Limited to <= LFS_ATTR_MAX and <= cache_size. Stored in superblock // configured cache_size. Limited to <= 8190. Stored in superblock and must
// and must be respected by other littlefs drivers. // be respected by other littlefs drivers.
#ifndef LFS_INLINE_MAX #ifndef LFS_INLINE_MAX
#define LFS_INLINE_MAX 0x1ffe #define LFS_INLINE_MAX 0x1ffe
#endif #endif
// Maximum size of custom attributes in bytes, may be redefined, but there is
// no real benefit to using a smaller LFS_ATTR_MAX. Limited to <= 8190. Stored
// in superblock and must be respected by other littlefs drivers.
#ifndef LFS_ATTR_MAX
#define LFS_ATTR_MAX 0x1ffe
#endif
// Possible error codes, these are negative to allow // Possible error codes, these are negative to allow
// valid positive return values // valid positive return values
enum lfs_error { enum lfs_error {
@@ -213,24 +212,25 @@ struct lfs_config {
// lookahead block. // lookahead block.
void *lookahead_buffer; void *lookahead_buffer;
// 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_max;
// Optional upper limit on length of file names in bytes. No downside for // Optional upper limit on length of file names in bytes. No downside for
// larger names except the size of the info struct which is controlled by // larger names except the size of the info struct which is controlled by
// the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX when zero. Stored in // the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX when zero. Stored in
// superblock and must be respected by other littlefs drivers. // superblock and must be respected by other littlefs drivers.
lfs_size_t name_max; lfs_size_t name_max;
// Optional upper limit on inlined files in bytes. Large inline files // Optional upper limit on inlined files in bytes. Inline files must be
// require a larger cache size, but if a file can be inlined it does not // backed by RAM, but if a file fits in RAM it can be inlined into its
// need its own data block. Must be smaller than cache_size and less than // directory block without needing its own data block. Must be <=
// LFS_INLINE_MAX. Defaults to min(LFS_INLINE_MAX, read_size) when zero. // cache_size and LFS_INLINE_MAX. Defaults to min(LFS_INLINE_MAX,
// Stored in superblock and must be respected by other littlefs drivers. // cache_size) when zero. Stored in superblock and must be respected by
// other littlefs drivers.
lfs_size_t inline_max; lfs_size_t inline_max;
// Optional upper limit on custom attributes in bytes. No downside for
// larger attributes size but must be <= 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_max;
}; };
// File info structure // File info structure
@@ -238,10 +238,13 @@ struct lfs_info {
// Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR // Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR
uint8_t type; uint8_t type;
// Size of the file, only valid for REG files // Size of the file, only valid for REG files. Limited to 32-bits.
lfs_size_t size; lfs_size_t size;
// Name of the file stored as a null-terminated string // Name of the file stored as a null-terminated string. Limited to
// LFS_NAME_MAX+1, which can be changed by redefining LFS_NAME_MAX to
// reduce RAM. LFS_NAME_MAX is stored in superblock and must be
// respected by other littlefs drivers.
char name[LFS_NAME_MAX+1]; char name[LFS_NAME_MAX+1];
}; };
@@ -340,9 +343,9 @@ typedef struct lfs_superblock {
lfs_size_t block_size; lfs_size_t block_size;
lfs_size_t block_count; lfs_size_t block_count;
lfs_size_t attr_max;
lfs_size_t name_max; lfs_size_t name_max;
lfs_size_t inline_max; lfs_size_t inline_max;
lfs_size_t attr_max;
} lfs_superblock_t; } lfs_superblock_t;
// The littlefs filesystem type // The littlefs filesystem type
@@ -377,9 +380,9 @@ typedef struct lfs {
const struct lfs_config *cfg; const struct lfs_config *cfg;
lfs_size_t block_size; lfs_size_t block_size;
lfs_size_t block_count; lfs_size_t block_count;
lfs_size_t attr_max;
lfs_size_t name_max; lfs_size_t name_max;
lfs_size_t inline_max; lfs_size_t inline_max;
lfs_size_t attr_max;
} lfs_t; } lfs_t;