mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	Cleaned up config usage in file logic
The main change here was to drop the in-place twiddling of custom attributes to match the internal attribute structures. The original thought was that this could allow the compiler to garbage collect more of the custom attribute logic when not used, but since this occurs in the common lfs_file_opencfg function, gc can't really happen. Not twiddling the user's structure is the polite thing to do, opens up the ability to store the lfs_attr structure in ROM, and avoids surprising the user if they attempt to use the structure for their own purposes. This means we can make the lfs_attr structure const and rely on the list in the lfs_file_config structure, similar to how we rely on the global lfs_config structure. Some other tweaks: - Dropped the global file_buffer, replaced entirely by per-file buffers. - Updated LFS_INLINE_MAX and LFS_ATTR_MAX to correct values - Added workaround for compiler bug related to zero initializer: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119
This commit is contained in:
		
							
								
								
									
										62
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -759,7 +759,7 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir, | |||||||
|     dir->tail[1] = tail[1]; |     dir->tail[1] = tail[1]; | ||||||
|     dir->erased = false; |     dir->erased = false; | ||||||
|     dir->split = split; |     dir->split = split; | ||||||
|     dir->locals = (lfs_globals_t){0}; |     dir->locals = (lfs_globals_t){{{0}}}; | ||||||
|  |  | ||||||
|     // don't write out yet, let caller take care of that |     // don't write out yet, let caller take care of that | ||||||
|     return 0; |     return 0; | ||||||
| @@ -775,7 +775,7 @@ static int lfs_dir_compact(lfs_t *lfs, | |||||||
|     // There's nothing special about our global delta, so feed it back |     // There's nothing special about our global delta, so feed it back | ||||||
|     // into the global global delta |     // into the global global delta | ||||||
|     lfs_globalsxor(&lfs->diff, &dir->locals); |     lfs_globalsxor(&lfs->diff, &dir->locals); | ||||||
|     dir->locals = (lfs_globals_t){0}; |     dir->locals = (lfs_globals_t){{{0}}}; | ||||||
|  |  | ||||||
|     // increment revision count |     // increment revision count | ||||||
|     dir->rev += 1; |     dir->rev += 1; | ||||||
| @@ -929,7 +929,7 @@ relocate: | |||||||
|     if (!relocated) { |     if (!relocated) { | ||||||
|         // successful commit, update globals |         // successful commit, update globals | ||||||
|         lfs_globalsxor(&dir->locals, &lfs->diff); |         lfs_globalsxor(&dir->locals, &lfs->diff); | ||||||
|         lfs->diff = (lfs_globals_t){0}; |         lfs->diff = (lfs_globals_t){{{0}}}; | ||||||
|     } else { |     } else { | ||||||
|         // update references if we relocated |         // update references if we relocated | ||||||
|         LFS_DEBUG("Relocating %d %d to %d %d", |         LFS_DEBUG("Relocating %d %d to %d %d", | ||||||
| @@ -1070,7 +1070,7 @@ compact: | |||||||
|         dir->etag = commit.ptag; |         dir->etag = commit.ptag; | ||||||
|         // successful commit, update globals |         // successful commit, update globals | ||||||
|         lfs_globalsxor(&dir->locals, &lfs->diff); |         lfs_globalsxor(&dir->locals, &lfs->diff); | ||||||
|         lfs->diff = (lfs_globals_t){0}; |         lfs->diff = (lfs_globals_t){{{0}}}; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // update globals that are affected |     // update globals that are affected | ||||||
| @@ -1142,7 +1142,7 @@ static int32_t lfs_dir_find(lfs_t *lfs, | |||||||
|         uint16_t tempcount = 0; |         uint16_t tempcount = 0; | ||||||
|         lfs_block_t temptail[2] = {0xffffffff, 0xffffffff}; |         lfs_block_t temptail[2] = {0xffffffff, 0xffffffff}; | ||||||
|         bool tempsplit = false; |         bool tempsplit = false; | ||||||
|         lfs_globals_t templocals = (lfs_globals_t){0}; |         lfs_globals_t templocals = (lfs_globals_t){{{0}}}; | ||||||
|  |  | ||||||
|         while (true) { |         while (true) { | ||||||
|             // extract next tag |             // extract next tag | ||||||
| @@ -1882,37 +1882,30 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | |||||||
|     file->id = lfs_tagid(tag); |     file->id = lfs_tagid(tag); | ||||||
|     file->flags = flags; |     file->flags = flags; | ||||||
|     file->pos = 0; |     file->pos = 0; | ||||||
|     file->attrs = NULL; |  | ||||||
|  |  | ||||||
|     if (cfg && cfg->attrs) { |     // fetch attrs | ||||||
|         // fetch attrs |     for (const struct lfs_attr *a = file->cfg->attrs; a; a = a->next) { | ||||||
|         for (const struct lfs_attr *a = cfg->attrs; a; a = a->next) { |         if ((file->flags & 3) != LFS_O_WRONLY) { | ||||||
|             if ((file->flags & 3) != LFS_O_WRONLY) { |             int32_t res = lfs_dir_get(lfs, &cwd, 0x7ffff000, | ||||||
|                 int32_t res = lfs_dir_get(lfs, &cwd, 0x7ffff000, |                     LFS_MKTAG(0x100 | a->type, file->id, a->size), a->buffer); | ||||||
|                         LFS_MKTAG(0x100 | a->type, file->id, a->size), a->buffer); |             if (res < 0 && res != LFS_ERR_NOENT) { | ||||||
|                 if (res < 0 && res != LFS_ERR_NOENT) { |                 return res; | ||||||
|                     return res; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if ((file->flags & 3) != LFS_O_RDONLY) { |  | ||||||
|                 if (a->size > lfs->attr_size) { |  | ||||||
|                     return LFS_ERR_NOSPC; |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 file->flags |= LFS_F_DIRTY; |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         file->attrs = cfg->attrs; |         if ((file->flags & 3) != LFS_O_RDONLY) { | ||||||
|  |             if (a->size > lfs->attr_size) { | ||||||
|  |                 return LFS_ERR_NOSPC; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             file->flags |= LFS_F_DIRTY; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // allocate buffer if needed |     // allocate buffer if needed | ||||||
|     file->cache.block = 0xffffffff; |     file->cache.block = 0xffffffff; | ||||||
|     if (file->cfg && file->cfg->buffer) { |     if (file->cfg->buffer) { | ||||||
|         file->cache.buffer = file->cfg->buffer; |         file->cache.buffer = file->cfg->buffer; | ||||||
|     } else if (lfs->cfg->file_buffer) { |  | ||||||
|         file->cache.buffer = lfs->cfg->file_buffer; |  | ||||||
|     } else if ((file->flags & 3) == LFS_O_RDONLY) { |     } else if ((file->flags & 3) == LFS_O_RDONLY) { | ||||||
|         file->cache.buffer = lfs_malloc(lfs->cfg->read_size); |         file->cache.buffer = lfs_malloc(lfs->cfg->read_size); | ||||||
|         if (!file->cache.buffer) { |         if (!file->cache.buffer) { | ||||||
| @@ -1954,7 +1947,8 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, | |||||||
|  |  | ||||||
| int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | ||||||
|         const char *path, int flags) { |         const char *path, int flags) { | ||||||
|     return lfs_file_opencfg(lfs, file, path, flags, NULL); |     static const struct lfs_file_config defaults = {0}; | ||||||
|  |     return lfs_file_opencfg(lfs, file, path, flags, &defaults); | ||||||
| } | } | ||||||
|  |  | ||||||
| int lfs_file_close(lfs_t *lfs, lfs_file_t *file) { | int lfs_file_close(lfs_t *lfs, lfs_file_t *file) { | ||||||
| @@ -1969,7 +1963,7 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // clean up memory |     // clean up memory | ||||||
|     if (!(file->cfg && file->cfg->buffer) && !lfs->cfg->file_buffer) { |     if (file->cfg->buffer) { | ||||||
|         lfs_free(file->cache.buffer); |         lfs_free(file->cache.buffer); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -2119,7 +2113,7 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | |||||||
|             int err = lfs_dir_commit(lfs, &cwd, |             int err = lfs_dir_commit(lfs, &cwd, | ||||||
|                     LFS_MKATTR(LFS_TYPE_CTZSTRUCT, file->id, |                     LFS_MKATTR(LFS_TYPE_CTZSTRUCT, file->id, | ||||||
|                         &file->ctz.head, sizeof(file->ctz), |                         &file->ctz.head, sizeof(file->ctz), | ||||||
|                     LFS_MKATTR(LFS_FROM_ATTRS, file->id, file->attrs, 0, |                     LFS_MKATTR(LFS_FROM_ATTRS, file->id, file->cfg->attrs, 0, | ||||||
|                     NULL))); |                     NULL))); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
| @@ -2128,7 +2122,7 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { | |||||||
|             int err = lfs_dir_commit(lfs, &cwd, |             int err = lfs_dir_commit(lfs, &cwd, | ||||||
|                     LFS_MKATTR(LFS_TYPE_INLINESTRUCT, file->id, |                     LFS_MKATTR(LFS_TYPE_INLINESTRUCT, file->id, | ||||||
|                             file->cache.buffer, file->ctz.size, |                             file->cache.buffer, file->ctz.size, | ||||||
|                     LFS_MKATTR(LFS_FROM_ATTRS, file->id, file->attrs, 0, |                     LFS_MKATTR(LFS_FROM_ATTRS, file->id, file->cfg->attrs, 0, | ||||||
|                     NULL))); |                     NULL))); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
| @@ -2237,7 +2231,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     if ((file->flags & LFS_F_INLINE) && |     if ((file->flags & LFS_F_INLINE) && | ||||||
|             file->pos + nsize >= lfs->cfg->inline_size) { |             file->pos + nsize >= lfs->inline_size) { | ||||||
|         // inline file doesn't fit anymore |         // inline file doesn't fit anymore | ||||||
|         file->block = 0xfffffffe; |         file->block = 0xfffffffe; | ||||||
|         file->off = file->pos; |         file->off = file->pos; | ||||||
| @@ -3365,7 +3359,7 @@ int lfs_scan(lfs_t *lfs) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     lfs_mdir_t dir = {.tail = {0, 1}}; |     lfs_mdir_t dir = {.tail = {0, 1}}; | ||||||
|     lfs->diff = (lfs_globals_t){0}; |     lfs->diff = (lfs_globals_t){{{0}}}; | ||||||
|  |  | ||||||
|     // iterate over all directory directory entries |     // iterate over all directory directory entries | ||||||
|     while (!lfs_pairisnull(dir.tail)) { |     while (!lfs_pairisnull(dir.tail)) { | ||||||
| @@ -3382,7 +3376,7 @@ int lfs_scan(lfs_t *lfs) { | |||||||
|     // TODO does this only run once? |     // TODO does this only run once? | ||||||
|     // TODO Should we inline this into init?? |     // TODO Should we inline this into init?? | ||||||
|     lfs_globalsxor(&lfs->globals, &lfs->diff); |     lfs_globalsxor(&lfs->globals, &lfs->diff); | ||||||
|     lfs->diff = (lfs_globals_t){0}; |     lfs->diff = (lfs_globals_t){{{0}}}; | ||||||
|     if (!lfs_pairisnull(lfs->globals.move.pair)) { |     if (!lfs_pairisnull(lfs->globals.move.pair)) { | ||||||
|         LFS_DEBUG("Found move %d %d %d", |         LFS_DEBUG("Found move %d %d %d", | ||||||
|                 lfs->globals.move.pair[0], |                 lfs->globals.move.pair[0], | ||||||
|   | |||||||
							
								
								
									
										11
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -54,16 +54,18 @@ typedef uint32_t lfs_block_t; | |||||||
| // read and prog cache, but if a file can be inline it does not need its own | // 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 | // data block. LFS_ATTR_MAX + LFS_INLINE_MAX must be <= 0xffff. Stored in | ||||||
| // superblock and must be respected by other littlefs drivers. | // superblock and must be respected by other littlefs drivers. | ||||||
|  | // TODO doc | ||||||
| #ifndef LFS_INLINE_MAX | #ifndef LFS_INLINE_MAX | ||||||
| #define LFS_INLINE_MAX 0x3ff | #define LFS_INLINE_MAX 0xfff | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // Maximum size of all attributes per file in bytes, may be redefined but a | // 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 | // 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 | // must be <= 0xffff. Stored in superblock and must be respected by other | ||||||
| // littlefs drivers. | // littlefs drivers. | ||||||
|  | // TODO doc | ||||||
| #ifndef LFS_ATTR_MAX | #ifndef LFS_ATTR_MAX | ||||||
| #define LFS_ATTR_MAX 0x3f | #define LFS_ATTR_MAX 0xfff | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| // Max name size in bytes, may be redefined to reduce the size of the | // Max name size in bytes, may be redefined to reduce the size of the | ||||||
| @@ -211,10 +213,6 @@ struct lfs_config { | |||||||
|     // lookahead block. |     // lookahead block. | ||||||
|     void *lookahead_buffer; |     void *lookahead_buffer; | ||||||
|  |  | ||||||
|     // Optional, statically allocated buffer for files. Must be program sized. |  | ||||||
|     // If enabled, only one file may be opened at a time. |  | ||||||
|     void *file_buffer; |  | ||||||
|  |  | ||||||
|     // Optional upper limit on inlined files in bytes. Large inline files |     // 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 |     // 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 |     // does not need its own data block. Must be smaller than the read size | ||||||
| @@ -317,7 +315,6 @@ typedef struct lfs_file { | |||||||
|     } ctz; |     } ctz; | ||||||
|  |  | ||||||
|     const struct lfs_file_config *cfg; |     const struct lfs_file_config *cfg; | ||||||
|     const struct lfs_attr *attrs; |  | ||||||
|     uint32_t flags; |     uint32_t flags; | ||||||
|     lfs_off_t pos; |     lfs_off_t pos; | ||||||
|     lfs_block_t block; |     lfs_block_t block; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user