mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 08:42:40 +01:00 
			
		
		
		
	Added different sources for commits, now with disk->disk moves
Previously, commits could only come from memory in RAM. This meant any entries had to be buffered in their entirety before they could be moved to a different directory pair. By adding parameters for specifying commits from existing entries stored on disk, we allow any sized entries to be moved between directory pairs with a fixed RAM cost.
This commit is contained in:
		
							
								
								
									
										85
									
								
								lfs.c
									
									
									
									
									
								
							
							
						
						
									
										85
									
								
								lfs.c
									
									
									
									
									
								
							| @@ -486,7 +486,18 @@ static int lfs_dir_fetch(lfs_t *lfs, | |||||||
| struct lfs_region { | struct lfs_region { | ||||||
|     lfs_off_t oldoff; |     lfs_off_t oldoff; | ||||||
|     lfs_size_t oldlen; |     lfs_size_t oldlen; | ||||||
|     const void *newdata; |  | ||||||
|  |     enum lfs_region_source { | ||||||
|  |         LFS_FROM_MEM, | ||||||
|  |         LFS_FROM_DISK, | ||||||
|  |     } source; | ||||||
|  |     union { | ||||||
|  |         const void *mem; | ||||||
|  |         struct { | ||||||
|  |             lfs_block_t block; | ||||||
|  |             lfs_off_t off; | ||||||
|  |         } disk; | ||||||
|  |     } u; | ||||||
|     lfs_size_t newlen; |     lfs_size_t newlen; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -527,42 +538,49 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             int i = 0; |             int i = 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 && | ||||||
|  |                         j == regions[i].newlen) { | ||||||
|  |                     oldoff += regions[i].oldlen; | ||||||
|  |                     i += 1; | ||||||
|  |                     j = 0; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 uint8_t data; | ||||||
|                 if (i < count && regions[i].oldoff == oldoff) { |                 if (i < count && regions[i].oldoff == oldoff) { | ||||||
|                     lfs_crc(&crc, regions[i].newdata, regions[i].newlen); |                     if (regions[i].source == LFS_FROM_DISK) { | ||||||
|                     err = lfs_bd_prog(lfs, dir->pair[0], |                         err = lfs_bd_read(lfs, regions[i].u.disk.block, | ||||||
|                             newoff, regions[i].newdata, regions[i].newlen); |                                 regions[i].u.disk.off + j, &data, 1); | ||||||
|                     if (err) { |                         if (err) { | ||||||
|                         if (err == LFS_ERR_CORRUPT) { |                             return err; | ||||||
|                             goto relocate; |  | ||||||
|                         } |                         } | ||||||
|                         return err; |                     } else { | ||||||
|  |                         data = ((const uint8_t *)regions[i].u.mem)[j]; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     oldoff += regions[i].oldlen; |                     j += 1; | ||||||
|                     newoff += regions[i].newlen; |  | ||||||
|                     i += 1; |  | ||||||
|                 } else { |                 } else { | ||||||
|                     uint8_t data; |  | ||||||
|                     err = lfs_bd_read(lfs, oldpair[1], oldoff, &data, 1); |                     err = lfs_bd_read(lfs, oldpair[1], oldoff, &data, 1); | ||||||
|                     if (err) { |                     if (err) { | ||||||
|                         return err; |                         return err; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     lfs_crc(&crc, &data, 1); |  | ||||||
|                     err = lfs_bd_prog(lfs, dir->pair[0], newoff, &data, 1); |  | ||||||
|                     if (err) { |  | ||||||
|                         if (err == LFS_ERR_CORRUPT) { |  | ||||||
|                             goto relocate; |  | ||||||
|                         } |  | ||||||
|                         return err; |  | ||||||
|                     } |  | ||||||
|  |  | ||||||
|                     oldoff += 1; |                     oldoff += 1; | ||||||
|                     newoff += 1; |  | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  |                 lfs_crc(&crc, &data, 1); | ||||||
|  |                 err = lfs_bd_prog(lfs, dir->pair[0], newoff, &data, 1); | ||||||
|  |                 if (err) { | ||||||
|  |                     if (err == LFS_ERR_CORRUPT) { | ||||||
|  |                         goto relocate; | ||||||
|  |                     } | ||||||
|  |                     return err; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 newoff += 1; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             crc = lfs_tole32(crc); |             crc = lfs_tole32(crc); | ||||||
| @@ -643,8 +661,10 @@ 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, (struct lfs_region[]){ | ||||||
|             {entry->off, sizeof(entry->d), &entry->d, sizeof(entry->d)}, |             {entry->off, sizeof(entry->d), | ||||||
|             {entry->off+sizeof(entry->d), entry->d.nlen, data, entry->d.nlen} |                 LFS_FROM_MEM, {.mem = &entry->d}, sizeof(entry->d)}, | ||||||
|  |             {entry->off+sizeof(entry->d), entry->d.nlen, | ||||||
|  |                 LFS_FROM_MEM, {.mem = data}, entry->d.nlen} | ||||||
|         }, data ? 2 : 1); |         }, data ? 2 : 1); | ||||||
|     lfs_entry_fromle32(&entry->d); |     lfs_entry_fromle32(&entry->d); | ||||||
|     return err; |     return err; | ||||||
| @@ -659,8 +679,10 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, | |||||||
|  |  | ||||||
|             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, (struct lfs_region[]){ | ||||||
|                     {entry->off, 0, &entry->d, sizeof(entry->d)}, |                     {entry->off, 0, | ||||||
|                     {entry->off, 0, data, entry->d.nlen} |                         LFS_FROM_MEM, {.mem = &entry->d}, sizeof(entry->d)}, | ||||||
|  |                     {entry->off, 0, | ||||||
|  |                         LFS_FROM_MEM, {.mem = data}, entry->d.nlen} | ||||||
|                 }, 2); |                 }, 2); | ||||||
|             lfs_entry_fromle32(&entry->d); |             lfs_entry_fromle32(&entry->d); | ||||||
|             return err; |             return err; | ||||||
| @@ -679,8 +701,10 @@ 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); | ||||||
|             err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ |             err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ | ||||||
|                     {entry->off, 0, &entry->d, sizeof(entry->d)}, |                     {entry->off, 0, | ||||||
|                     {entry->off, 0, data, entry->d.nlen} |                         LFS_FROM_MEM, {.mem = &entry->d}, sizeof(entry->d)}, | ||||||
|  |                     {entry->off, 0, | ||||||
|  |                         LFS_FROM_MEM, {.mem = data}, entry->d.nlen} | ||||||
|                 }, 2); |                 }, 2); | ||||||
|             lfs_entry_fromle32(&entry->d); |             lfs_entry_fromle32(&entry->d); | ||||||
|             if (err) { |             if (err) { | ||||||
| @@ -720,7 +744,8 @@ static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { | |||||||
|  |  | ||||||
|     // 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), NULL, 0}, |             {entry->off, lfs_entry_size(entry), | ||||||
|  |                 LFS_FROM_MEM, {.mem = NULL}, 0}, | ||||||
|         }, 1); |         }, 1); | ||||||
|     if (err) { |     if (err) { | ||||||
|         return err; |         return err; | ||||||
| @@ -2153,7 +2178,7 @@ int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { | |||||||
|     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), |                 {sizeof(superdir.d), sizeof(superblock.d), | ||||||
|                  &superblock.d, sizeof(superblock.d)} |                     LFS_FROM_MEM, {.mem = &superblock.d}, sizeof(superblock.d)} | ||||||
|             }, 1); |             }, 1); | ||||||
|         if (err && err != LFS_ERR_CORRUPT) { |         if (err && err != LFS_ERR_CORRUPT) { | ||||||
|             return err; |             return err; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user