mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	WIP adopted lisp-like dsl for more flexibility
This commit is contained in:
		
							
								
								
									
										114
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										114
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -474,32 +474,36 @@ static int lfs_dir_fetch(lfs_t *lfs, | |||||||
| } | } | ||||||
|  |  | ||||||
| struct lfs_region { | struct lfs_region { | ||||||
|     lfs_off_t oldoff; |     enum { | ||||||
|     lfs_size_t oldlen; |  | ||||||
|  |  | ||||||
|     enum lfs_region_source { |  | ||||||
|         LFS_FROM_MEM, |         LFS_FROM_MEM, | ||||||
|         LFS_FROM_DISK, |         LFS_FROM_DISK, | ||||||
|     } source; |     } source; | ||||||
|  |  | ||||||
|  |     lfs_off_t oldoff; | ||||||
|  |     lfs_size_t oldlen; | ||||||
|     union { |     union { | ||||||
|         const void *mem; |         struct { | ||||||
|  |             const void *data; | ||||||
|  |         } m; | ||||||
|         struct { |         struct { | ||||||
|             lfs_block_t block; |             lfs_block_t block; | ||||||
|             lfs_off_t off; |             lfs_off_t off; | ||||||
|         } disk; |         } d; | ||||||
|     } u; |     } u; | ||||||
|     lfs_size_t newlen; |     lfs_size_t newlen; | ||||||
|  |  | ||||||
|  |     struct lfs_region *next; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | ||||||
|         const struct lfs_region *regions, int count) { |         struct lfs_region *region) { | ||||||
|     // increment revision count |     // increment revision count | ||||||
|     dir->d.rev += 1; |     dir->d.rev += 1; | ||||||
|  |  | ||||||
|     // keep pairs in order such that pair[0] is most recent |     // keep pairs in order such that pair[0] is most recent | ||||||
|     lfs_pairswap(dir->pair); |     lfs_pairswap(dir->pair); | ||||||
|     for (int i = 0; i < count; i++) { |     for (struct lfs_region *r = region; r; r = r->next) { | ||||||
|         dir->d.size += regions[i].newlen - regions[i].oldlen; |         dir->d.size += r->newlen - r->oldlen; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const lfs_block_t oldpair[2] = {dir->pair[0], dir->pair[1]}; |     const lfs_block_t oldpair[2] = {dir->pair[0], dir->pair[1]}; | ||||||
| @@ -527,28 +531,27 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|                 return err; |                 return err; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             int i = 0; |             struct lfs_region *r = region; | ||||||
|             int j = 0; |             int j = 0; | ||||||
|             lfs_off_t oldoff = sizeof(dir->d); |             lfs_off_t oldoff = sizeof(dir->d); | ||||||
|             lfs_off_t newoff = sizeof(dir->d); |             lfs_off_t newoff = sizeof(dir->d); | ||||||
|             while (newoff < (0x7fffffff & dir->d.size)-4) { |             while (newoff < (0x7fffffff & dir->d.size)-4) { | ||||||
|                 while (i < count && oldoff == regions[i].oldoff && |                 while (r && r->oldoff == oldoff && r->newlen == j) { | ||||||
|                         j == regions[i].newlen) { |                     oldoff += r->oldlen; | ||||||
|                     oldoff += regions[i].oldlen; |                     r = r->next; | ||||||
|                     i += 1; |  | ||||||
|                     j = 0; |                     j = 0; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 uint8_t data; |                 uint8_t data; | ||||||
|                 if (i < count && regions[i].oldoff == oldoff) { |                 if (r && r->oldoff == oldoff) { | ||||||
|                     if (regions[i].source == LFS_FROM_DISK) { |                     if (r->source == LFS_FROM_DISK) { | ||||||
|                         err = lfs_bd_read(lfs, regions[i].u.disk.block, |                         err = lfs_bd_read(lfs, r->u.d.block, | ||||||
|                                 regions[i].u.disk.off + j, &data, 1); |                                 r->u.d.off + j, &data, 1); | ||||||
|                         if (err) { |                         if (err) { | ||||||
|                             return err; |                             return err; | ||||||
|                         } |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         data = ((const uint8_t *)regions[i].u.mem)[j]; |                         data = ((const uint8_t *)r->u.m.data)[j]; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     j += 1; |                     j += 1; | ||||||
| @@ -650,12 +653,15 @@ relocate: | |||||||
| 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, const void *data) { |         lfs_entry_t *entry, const void *data) { | ||||||
|     lfs_entry_tole32(&entry->d); |     lfs_entry_tole32(&entry->d); | ||||||
|     int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ |     int err = lfs_dir_commit(lfs, dir, | ||||||
|             {entry->off, sizeof(entry->d), |             &(struct lfs_region){ | ||||||
|                 LFS_FROM_MEM, {.mem = &entry->d}, sizeof(entry->d)}, |                 LFS_FROM_MEM, entry->off, sizeof(entry->d), | ||||||
|             {entry->off+sizeof(entry->d), entry->d.nlen, |                 {.m.data = &entry->d}, sizeof(entry->d), | ||||||
|                 LFS_FROM_MEM, {.mem = data}, entry->d.nlen} |             data ? | ||||||
|         }, data ? 2 : 1); |                 &(struct lfs_region){ | ||||||
|  |                     LFS_FROM_MEM, entry->off+sizeof(entry->d), entry->d.nlen, | ||||||
|  |                     {.m.data = data}, entry->d.nlen} | ||||||
|  |                 : NULL}); | ||||||
|     lfs_entry_fromle32(&entry->d); |     lfs_entry_fromle32(&entry->d); | ||||||
|     return err; |     return err; | ||||||
| } | } | ||||||
| @@ -668,12 +674,13 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|             entry->off = dir->d.size - 4; |             entry->off = dir->d.size - 4; | ||||||
|  |  | ||||||
|             lfs_entry_tole32(&entry->d); |             lfs_entry_tole32(&entry->d); | ||||||
|             int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ |             int err = lfs_dir_commit(lfs, dir, | ||||||
|                     {entry->off, 0, |                     &(struct lfs_region){ | ||||||
|                         LFS_FROM_MEM, {.mem = &entry->d}, sizeof(entry->d)}, |                         LFS_FROM_MEM, entry->off, 0, | ||||||
|                     {entry->off, 0, |                         {.m.data = &entry->d}, sizeof(entry->d), | ||||||
|                         LFS_FROM_MEM, {.mem = data}, entry->d.nlen} |                     &(struct lfs_region){ | ||||||
|                 }, 2); |                         LFS_FROM_MEM, entry->off, 0, | ||||||
|  |                         {.m.data = data}, entry->d.nlen}}); | ||||||
|             lfs_entry_fromle32(&entry->d); |             lfs_entry_fromle32(&entry->d); | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -690,12 +697,13 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|             dir->d.tail[1] = olddir.d.tail[1]; |             dir->d.tail[1] = olddir.d.tail[1]; | ||||||
|             entry->off = dir->d.size - 4; |             entry->off = dir->d.size - 4; | ||||||
|             lfs_entry_tole32(&entry->d); |             lfs_entry_tole32(&entry->d); | ||||||
|             err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ |             err = lfs_dir_commit(lfs, dir, | ||||||
|                     {entry->off, 0, |                     &(struct lfs_region){ | ||||||
|                         LFS_FROM_MEM, {.mem = &entry->d}, sizeof(entry->d)}, |                         LFS_FROM_MEM, entry->off, 0, | ||||||
|                     {entry->off, 0, |                         {.m.data = &entry->d}, sizeof(entry->d), | ||||||
|                         LFS_FROM_MEM, {.mem = data}, entry->d.nlen} |                     &(struct lfs_region){ | ||||||
|                 }, 2); |                         LFS_FROM_MEM, entry->off, 0, | ||||||
|  |                         {.m.data = data}, entry->d.nlen}}); | ||||||
|             lfs_entry_fromle32(&entry->d); |             lfs_entry_fromle32(&entry->d); | ||||||
|             if (err) { |             if (err) { | ||||||
|                 return err; |                 return err; | ||||||
| @@ -704,7 +712,7 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|             olddir.d.size |= 0x80000000; |             olddir.d.size |= 0x80000000; | ||||||
|             olddir.d.tail[0] = dir->pair[0]; |             olddir.d.tail[0] = dir->pair[0]; | ||||||
|             olddir.d.tail[1] = dir->pair[1]; |             olddir.d.tail[1] = dir->pair[1]; | ||||||
|             return lfs_dir_commit(lfs, &olddir, NULL, 0); |             return lfs_dir_commit(lfs, &olddir, NULL); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         int err = lfs_dir_fetch(lfs, dir, dir->d.tail); |         int err = lfs_dir_fetch(lfs, dir, dir->d.tail); | ||||||
| @@ -728,15 +736,14 @@ static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | |||||||
|             pdir.d.size &= dir->d.size | 0x7fffffff; |             pdir.d.size &= dir->d.size | 0x7fffffff; | ||||||
|             pdir.d.tail[0] = dir->d.tail[0]; |             pdir.d.tail[0] = dir->d.tail[0]; | ||||||
|             pdir.d.tail[1] = dir->d.tail[1]; |             pdir.d.tail[1] = dir->d.tail[1]; | ||||||
|             return lfs_dir_commit(lfs, &pdir, NULL, 0); |             return lfs_dir_commit(lfs, &pdir, NULL); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // shift out the entry |     // shift out the entry | ||||||
|     int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ |     int err = lfs_dir_commit(lfs, dir, &(struct lfs_region){ | ||||||
|             {entry->off, lfs_entry_size(entry), |             LFS_FROM_MEM, entry->off, lfs_entry_size(entry), | ||||||
|                 LFS_FROM_MEM, {.mem = NULL}, 0}, |             {.m.data = NULL}, 0}); | ||||||
|         }, 1); |  | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -941,7 +948,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { | |||||||
|     dir.d.tail[0] = cwd.d.tail[0]; |     dir.d.tail[0] = cwd.d.tail[0]; | ||||||
|     dir.d.tail[1] = cwd.d.tail[1]; |     dir.d.tail[1] = cwd.d.tail[1]; | ||||||
|  |  | ||||||
|     err = lfs_dir_commit(lfs, &dir, NULL, 0); |     err = lfs_dir_commit(lfs, &dir, NULL); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -1911,7 +1918,7 @@ int lfs_remove(lfs_t *lfs, const char *path) { | |||||||
|         cwd.d.tail[0] = dir.d.tail[0]; |         cwd.d.tail[0] = dir.d.tail[0]; | ||||||
|         cwd.d.tail[1] = dir.d.tail[1]; |         cwd.d.tail[1] = dir.d.tail[1]; | ||||||
|  |  | ||||||
|         err = lfs_dir_commit(lfs, &cwd, NULL, 0); |         err = lfs_dir_commit(lfs, &cwd, NULL); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -2028,7 +2035,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { | |||||||
|         newcwd.d.tail[0] = dir.d.tail[0]; |         newcwd.d.tail[0] = dir.d.tail[0]; | ||||||
|         newcwd.d.tail[1] = dir.d.tail[1]; |         newcwd.d.tail[1] = dir.d.tail[1]; | ||||||
|  |  | ||||||
|         err = lfs_dir_commit(lfs, &newcwd, NULL, 0); |         err = lfs_dir_commit(lfs, &newcwd, NULL); | ||||||
|         if (err) { |         if (err) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -2138,7 +2145,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     err = lfs_dir_commit(lfs, &root, NULL, 0); |     err = lfs_dir_commit(lfs, &root, NULL); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
|     } |     } | ||||||
| @@ -2166,10 +2173,9 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     lfs_superblock_tole32(&superblock.d); |     lfs_superblock_tole32(&superblock.d); | ||||||
|     bool valid = false; |     bool valid = false; | ||||||
|     for (int i = 0; i < 2; i++) { |     for (int i = 0; i < 2; i++) { | ||||||
|         err = lfs_dir_commit(lfs, &superdir, (struct lfs_region[]){ |         err = lfs_dir_commit(lfs, &superdir, &(struct lfs_region){ | ||||||
|                 {sizeof(superdir.d), sizeof(superblock.d), |                 LFS_FROM_MEM, sizeof(superdir.d), sizeof(superblock.d), | ||||||
|                     LFS_FROM_MEM, {.mem = &superblock.d}, sizeof(superblock.d)} |                 {.m.data = &superblock.d}, sizeof(superblock.d)}); | ||||||
|             }, 1); |  | ||||||
|         if (err && err != LFS_ERR_CORRUPT) { |         if (err && err != LFS_ERR_CORRUPT) { | ||||||
|             return err; |             return err; | ||||||
|         } |         } | ||||||
| @@ -2460,7 +2466,7 @@ static int lfs_relocate(lfs_t *lfs, | |||||||
|         parent.d.tail[0] = newpair[0]; |         parent.d.tail[0] = newpair[0]; | ||||||
|         parent.d.tail[1] = newpair[1]; |         parent.d.tail[1] = newpair[1]; | ||||||
|  |  | ||||||
|         return lfs_dir_commit(lfs, &parent, NULL, 0); |         return lfs_dir_commit(lfs, &parent, NULL); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // couldn't find dir, must be new |     // couldn't find dir, must be new | ||||||
| @@ -2502,7 +2508,7 @@ int lfs_deorphan(lfs_t *lfs) { | |||||||
|                 pdir.d.tail[0] = cwd.d.tail[0]; |                 pdir.d.tail[0] = cwd.d.tail[0]; | ||||||
|                 pdir.d.tail[1] = cwd.d.tail[1]; |                 pdir.d.tail[1] = cwd.d.tail[1]; | ||||||
|  |  | ||||||
|                 err = lfs_dir_commit(lfs, &pdir, NULL, 0); |                 err = lfs_dir_commit(lfs, &pdir, NULL); | ||||||
|                 if (err) { |                 if (err) { | ||||||
|                     return err; |                     return err; | ||||||
|                 } |                 } | ||||||
| @@ -2518,7 +2524,7 @@ int lfs_deorphan(lfs_t *lfs) { | |||||||
|                 pdir.d.tail[0] = entry.d.u.dir[0]; |                 pdir.d.tail[0] = entry.d.u.dir[0]; | ||||||
|                 pdir.d.tail[1] = entry.d.u.dir[1]; |                 pdir.d.tail[1] = entry.d.u.dir[1]; | ||||||
|  |  | ||||||
|                 err = lfs_dir_commit(lfs, &pdir, NULL, 0); |                 err = lfs_dir_commit(lfs, &pdir, NULL); | ||||||
|                 if (err) { |                 if (err) { | ||||||
|                     return err; |                     return err; | ||||||
|                 } |                 } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user