mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	Added size field to entry structure
The size field is redundant, since an entry's size can be determined from the nlen+elen+alen+4. However, as you may have guessed from that expression, calculating the size this way is a bit roundabout and inefficient. Despite its redundancy, it's cheaper to store the size in the entry, though with a minor RAM cost. Note, extra care must now be taken to make sure these size and len fields don't fall out of sync.
This commit is contained in:
		
							
								
								
									
										82
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										82
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -397,10 +397,6 @@ static inline bool lfs_pairsync( | |||||||
|            (paira[0] == pairb[1] && paira[1] == pairb[0]); |            (paira[0] == pairb[1] && paira[1] == pairb[0]); | ||||||
| } | } | ||||||
|  |  | ||||||
| static inline lfs_size_t lfs_entry_size(const lfs_entry_t *entry) { |  | ||||||
|     return 4 + entry->d.elen + entry->d.alen + entry->d.nlen; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir) { | static int lfs_dir_alloc(lfs_t *lfs, lfs_dir_t *dir) { | ||||||
|     // allocate pair of dir blocks |     // allocate pair of dir blocks | ||||||
|     for (int i = 0; i < 2; i++) { |     for (int i = 0; i < 2; i++) { | ||||||
| @@ -677,14 +673,14 @@ relocate: | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_dir_append_(lfs_t *lfs, lfs_dir_t *dir, | static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | ||||||
|         lfs_off_t *off, lfs_size_t size, struct lfs_region *regions) { |         lfs_entry_t *entry, struct lfs_region *regions) { | ||||||
|     // check if we fit, if top bit is set we do not and move on |     // check if we fit, if top bit is set we do not and move on | ||||||
|     while (true) { |     while (true) { | ||||||
|         if ((0x7fffffff & dir->d.size) + size <= lfs->cfg->block_size) { |         if ((0x7fffffff & dir->d.size) + entry->size <= lfs->cfg->block_size) { | ||||||
|             *off = dir->d.size - 4; |             entry->off = dir->d.size - 4; | ||||||
|             for (struct lfs_region *r = regions; r; r = r->next) { |             for (struct lfs_region *r = regions; r; r = r->next) { | ||||||
|                 r->off += *off; |                 r->off += entry->off; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             return lfs_dir_commit(lfs, dir, regions); |             return lfs_dir_commit(lfs, dir, regions); | ||||||
| @@ -700,9 +696,9 @@ static int lfs_dir_append_(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|  |  | ||||||
|             dir->d.tail[0] = olddir.d.tail[0]; |             dir->d.tail[0] = olddir.d.tail[0]; | ||||||
|             dir->d.tail[1] = olddir.d.tail[1]; |             dir->d.tail[1] = olddir.d.tail[1]; | ||||||
|             *off = dir->d.size - 4; |             entry->off = dir->d.size - 4; | ||||||
|             for (struct lfs_region *r = regions; r; r = r->next) { |             for (struct lfs_region *r = regions; r; r = r->next) { | ||||||
|                 r->off += *off; |                 r->off += entry->off; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             err = lfs_dir_commit(lfs, dir, regions); |             err = lfs_dir_commit(lfs, dir, regions); | ||||||
| @@ -723,10 +719,10 @@ static int lfs_dir_append_(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_dir_remove_(lfs_t *lfs, lfs_dir_t *dir, | static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, | ||||||
|         lfs_off_t off, lfs_size_t size) { |         const lfs_entry_t *entry) { | ||||||
|     // check if we should just drop the directory block |     // check if we should just drop the directory block | ||||||
|     if ((dir->d.size & 0x7fffffff) == sizeof(dir->d)+4 + size) { |     if ((dir->d.size & 0x7fffffff) == sizeof(dir->d)+4 + entry->size) { | ||||||
|         lfs_dir_t pdir; |         lfs_dir_t pdir; | ||||||
|         int res = lfs_pred(lfs, dir->pair, &pdir); |         int res = lfs_pred(lfs, dir->pair, &pdir); | ||||||
|         if (res < 0) { |         if (res < 0) { | ||||||
| @@ -744,7 +740,7 @@ static int lfs_dir_remove_(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|     // shift out the entry |     // shift out the entry | ||||||
|     int err = lfs_dir_commit(lfs, dir, |     int err = lfs_dir_commit(lfs, dir, | ||||||
|             &(struct lfs_region){ |             &(struct lfs_region){ | ||||||
|                 off, -size, |                 entry->off, -entry->size, | ||||||
|                 lfs_commit_mem, NULL, 0}); |                 lfs_commit_mem, NULL, 0}); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
| @@ -753,20 +749,20 @@ static int lfs_dir_remove_(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|     // shift over any files/directories that are affected |     // shift over any files/directories that are affected | ||||||
|     for (lfs_file_t *f = lfs->files; f; f = f->next) { |     for (lfs_file_t *f = lfs->files; f; f = f->next) { | ||||||
|         if (lfs_paircmp(f->pair, dir->pair) == 0) { |         if (lfs_paircmp(f->pair, dir->pair) == 0) { | ||||||
|             if (f->poff == off) { |             if (f->poff == entry->off) { | ||||||
|                 f->pair[0] = 0xffffffff; |                 f->pair[0] = 0xffffffff; | ||||||
|                 f->pair[1] = 0xffffffff; |                 f->pair[1] = 0xffffffff; | ||||||
|             } else if (f->poff > off) { |             } else if (f->poff > entry->off) { | ||||||
|                 f->poff -= size; |                 f->poff -= entry->size; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     for (lfs_dir_t *d = lfs->dirs; d; d = d->next) { |     for (lfs_dir_t *d = lfs->dirs; d; d = d->next) { | ||||||
|         if (lfs_paircmp(d->pair, dir->pair) == 0) { |         if (lfs_paircmp(d->pair, dir->pair) == 0) { | ||||||
|             if (d->off > off) { |             if (d->off > entry->off) { | ||||||
|                 d->off -= size; |                 d->off -= entry->size; | ||||||
|                 d->pos -= size; |                 d->pos -= entry->size; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -774,17 +770,6 @@ static int lfs_dir_remove_(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, |  | ||||||
|         lfs_entry_t *entry, struct lfs_region *regions) { |  | ||||||
|     return lfs_dir_append_(lfs, dir, |  | ||||||
|             &entry->off, lfs_entry_size(entry), regions); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { |  | ||||||
|     return lfs_dir_remove_(lfs, dir, |  | ||||||
|             entry->off, lfs_entry_size(entry)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir, | static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir, | ||||||
|         lfs_entry_t *entry, struct lfs_region *regions) { |         lfs_entry_t *entry, struct lfs_region *regions) { | ||||||
|     lfs_ssize_t diff = 0; |     lfs_ssize_t diff = 0; | ||||||
| @@ -823,7 +808,7 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|     } else { |     } else { | ||||||
|         lfs_dir_t olddir = *dir; |         lfs_dir_t olddir = *dir; | ||||||
|         lfs_off_t oldoff = entry->off; |         lfs_off_t oldoff = entry->off; | ||||||
|         lfs_size_t oldsize = lfs_entry_size(entry) - diff; |         lfs_size_t oldsize = entry->size - diff; | ||||||
|  |  | ||||||
|         // mark as moving |         // mark as moving | ||||||
|         entry->d.type |= LFS_STRUCT_MOVED; |         entry->d.type |= LFS_STRUCT_MOVED; | ||||||
| @@ -839,7 +824,7 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|         // append updated entry |         // append updated entry | ||||||
|         err = lfs_dir_append(lfs, dir, entry, |         err = lfs_dir_append(lfs, dir, entry, | ||||||
|                 &(struct lfs_region){ |                 &(struct lfs_region){ | ||||||
|                     0, +lfs_entry_size(entry), |                     0, +entry->size, | ||||||
|                     lfs_commit_disk, &(struct lfs_commit_disk){ |                     lfs_commit_disk, &(struct lfs_commit_disk){ | ||||||
|                         olddir.pair[0], entry->off, regions}, oldsize}); |                         olddir.pair[0], entry->off, regions}, oldsize}); | ||||||
|         if (err) { |         if (err) { | ||||||
| @@ -847,13 +832,10 @@ static int lfs_dir_update(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         // remove old entry |         // remove old entry | ||||||
|         err = lfs_dir_remove_(lfs, dir, oldoff, oldsize); |         err = lfs_dir_remove(lfs, dir, &(lfs_entry_t){oldoff, oldsize}); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // TODO remove file under file? |  | ||||||
|         // TODO need to shift entries? |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     return 0; |     return 0; | ||||||
| @@ -883,8 +865,9 @@ static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     entry->off = dir->off; |     entry->off = dir->off; | ||||||
|     dir->off += lfs_entry_size(entry); |     entry->size = 4 + entry->d.elen + entry->d.alen + entry->d.nlen; | ||||||
|     dir->pos += lfs_entry_size(entry); |     dir->off += entry->size; | ||||||
|  |     dir->pos += entry->size; | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -903,9 +886,6 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|         if (pathname[0] == '\0') { |         if (pathname[0] == '\0') { | ||||||
|             *entry = (lfs_entry_t){ |             *entry = (lfs_entry_t){ | ||||||
|                 .d.type = LFS_STRUCT_DIR | LFS_TYPE_DIR, |                 .d.type = LFS_STRUCT_DIR | LFS_TYPE_DIR, | ||||||
|                 .d.elen = sizeof(entry->d) - 4, |  | ||||||
|                 .d.alen = 0, |  | ||||||
|                 .d.nlen = 0, |  | ||||||
|                 .d.u.dir[0] = lfs->root[0], |                 .d.u.dir[0] = lfs->root[0], | ||||||
|                 .d.u.dir[1] = lfs->root[1], |                 .d.u.dir[1] = lfs->root[1], | ||||||
|             }; |             }; | ||||||
| @@ -960,7 +940,7 @@ static int lfs_dir_find(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             int res = lfs_bd_cmp(lfs, dir->pair[0], |             int res = lfs_bd_cmp(lfs, dir->pair[0], | ||||||
|                     entry->off + 4+entry->d.elen+entry->d.alen, |                     entry->off + entry->size - pathlen, | ||||||
|                     pathname, pathlen); |                     pathname, pathlen); | ||||||
|             if (res < 0) { |             if (res < 0) { | ||||||
|                 return res; |                 return res; | ||||||
| @@ -1046,6 +1026,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { | |||||||
|     entry.d.nlen = strlen(path); |     entry.d.nlen = strlen(path); | ||||||
|     entry.d.u.dir[0] = dir.pair[0]; |     entry.d.u.dir[0] = dir.pair[0]; | ||||||
|     entry.d.u.dir[1] = dir.pair[1]; |     entry.d.u.dir[1] = dir.pair[1]; | ||||||
|  |     entry.size = 4 + entry.d.elen + entry.d.alen + entry.d.nlen; | ||||||
|  |  | ||||||
|     cwd.d.tail[0] = dir.pair[0]; |     cwd.d.tail[0] = dir.pair[0]; | ||||||
|     cwd.d.tail[1] = dir.pair[1]; |     cwd.d.tail[1] = dir.pair[1]; | ||||||
| @@ -1164,7 +1145,7 @@ int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     int err = lfs_bd_read(lfs, dir->pair[0], |     int err = lfs_bd_read(lfs, dir->pair[0], | ||||||
|             entry.off + 4+entry.d.elen+entry.d.alen, |             entry.off + entry.size - entry.d.nlen, | ||||||
|             info->name, entry.d.nlen); |             info->name, entry.d.nlen); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
| @@ -1440,6 +1421,8 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, | |||||||
|         entry.d.nlen = strlen(path); |         entry.d.nlen = strlen(path); | ||||||
|         entry.d.u.file.head = 0xffffffff; |         entry.d.u.file.head = 0xffffffff; | ||||||
|         entry.d.u.file.size = 0; |         entry.d.u.file.size = 0; | ||||||
|  |         entry.size = 4 + entry.d.elen + entry.d.alen + entry.d.nlen; | ||||||
|  |  | ||||||
|         err = lfs_dir_append(lfs, &cwd, &entry, |         err = lfs_dir_append(lfs, &cwd, &entry, | ||||||
|                 &(struct lfs_region){ |                 &(struct lfs_region){ | ||||||
|                     0, +sizeof(entry.d), |                     0, +sizeof(entry.d), | ||||||
| @@ -1959,7 +1942,7 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { | |||||||
|         strcpy(info->name, "/"); |         strcpy(info->name, "/"); | ||||||
|     } else { |     } else { | ||||||
|         err = lfs_bd_read(lfs, cwd.pair[0], |         err = lfs_bd_read(lfs, cwd.pair[0], | ||||||
|                 entry.off + 4+entry.d.elen+entry.d.alen, |                 entry.off + entry.size - entry.d.nlen, | ||||||
|                 info->name, entry.d.nlen); |                 info->name, entry.d.nlen); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
| @@ -2272,7 +2255,6 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|  |  | ||||||
|     // write superblocks |     // write superblocks | ||||||
|     lfs_superblock_t superblock = { |     lfs_superblock_t superblock = { | ||||||
|         .off = sizeof(superdir.d), |  | ||||||
|         .d.type = LFS_STRUCT_DIR | LFS_TYPE_SUPERBLOCK, |         .d.type = LFS_STRUCT_DIR | LFS_TYPE_SUPERBLOCK, | ||||||
|         .d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4, |         .d.elen = sizeof(superblock.d) - sizeof(superblock.d.magic) - 4, | ||||||
|         .d.nlen = sizeof(superblock.d.magic), |         .d.nlen = sizeof(superblock.d.magic), | ||||||
| @@ -2374,8 +2356,6 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     // iterate over metadata pairs |     // iterate over metadata pairs | ||||||
|     lfs_dir_t dir; |  | ||||||
|     lfs_entry_t entry; |  | ||||||
|     lfs_block_t cwd[2] = {0, 1}; |     lfs_block_t cwd[2] = {0, 1}; | ||||||
|  |  | ||||||
|     while (true) { |     while (true) { | ||||||
| @@ -2386,12 +2366,14 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         lfs_dir_t dir; | ||||||
|         int err = lfs_dir_fetch(lfs, &dir, cwd); |         int err = lfs_dir_fetch(lfs, &dir, cwd); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // iterate over contents |         // iterate over contents | ||||||
|  |         lfs_entry_t entry; | ||||||
|         while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) { |         while (dir.off + sizeof(entry.d) <= (0x7fffffff & dir.d.size)-4) { | ||||||
|             err = lfs_bd_read(lfs, dir.pair[0], dir.off, |             err = lfs_bd_read(lfs, dir.pair[0], dir.off, | ||||||
|                     &entry.d, sizeof(entry.d)); |                     &entry.d, sizeof(entry.d)); | ||||||
| @@ -2400,7 +2382,7 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) { | |||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             dir.off += lfs_entry_size(&entry); |             dir.off += 4 + entry.d.elen + entry.d.alen + entry.d.nlen; | ||||||
|             if ((0x70 & entry.d.type) == LFS_STRUCT_CTZ) { |             if ((0x70 & entry.d.type) == LFS_STRUCT_CTZ) { | ||||||
|                 err = lfs_ctz_traverse(lfs, &lfs->rcache, NULL, |                 err = lfs_ctz_traverse(lfs, &lfs->rcache, NULL, | ||||||
|                         entry.d.u.file.head, entry.d.u.file.size, cb, data); |                         entry.d.u.file.head, entry.d.u.file.size, cb, data); | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								lfs.h
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								lfs.h
									
									
									
									
									
								
							| @@ -196,6 +196,7 @@ struct lfs_info { | |||||||
| /// littlefs data structures /// | /// littlefs data structures /// | ||||||
| typedef struct lfs_entry { | typedef struct lfs_entry { | ||||||
|     lfs_off_t off; |     lfs_off_t off; | ||||||
|  |     lfs_size_t size; | ||||||
|  |  | ||||||
|     struct lfs_disk_entry { |     struct lfs_disk_entry { | ||||||
|         uint8_t type; |         uint8_t type; | ||||||
| @@ -249,8 +250,6 @@ typedef struct lfs_dir { | |||||||
| } lfs_dir_t; | } lfs_dir_t; | ||||||
|  |  | ||||||
| typedef struct lfs_superblock { | typedef struct lfs_superblock { | ||||||
|     lfs_off_t off; |  | ||||||
|  |  | ||||||
|     struct lfs_disk_superblock { |     struct lfs_disk_superblock { | ||||||
|         uint8_t type; |         uint8_t type; | ||||||
|         uint8_t elen; |         uint8_t elen; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user