mirror of
				https://github.com/eledio-devices/thirdparty-littlefs.git
				synced 2025-10-31 16:14:16 +01:00 
			
		
		
		
	Added proper handling of orphans
Unfortunately, threading all dir blocks in a linked-list did not come without problems. While it's possible to atomically add a dir to the linked list (by adding the new dir into the linked-list position immediately after it's parent, requiring only one atomic update to the parent block), it is not easy to make sure the linked-list is in a state that always allows atomic removal of dirs. The simple solution is to allow this non-atomic removal, with an additional step to remove any orphans that could have been created by a power-loss. This deorphan step is only run if the normal allocator has failed.
This commit is contained in:
		| @@ -14,6 +14,8 @@ | ||||
| #include <dirent.h> | ||||
| #include <sys/stat.h> | ||||
| #include <unistd.h> | ||||
| #include <assert.h> | ||||
| #include <stdbool.h> | ||||
|  | ||||
|  | ||||
| // Block device emulated on existing filesystem | ||||
| @@ -76,12 +78,10 @@ int lfs_emubd_read(lfs_emubd_t *emu, lfs_block_t block, | ||||
|     uint8_t *data = buffer; | ||||
|  | ||||
|     // Check if read is valid | ||||
|     if (!(off % emu->info.read_size == 0 && | ||||
|          size % emu->info.read_size == 0 && | ||||
|          ((uint64_t)block*emu->info.erase_size + off + size | ||||
|           < emu->info.total_size))) { | ||||
|         return -EINVAL; | ||||
|     } | ||||
|     assert(off % emu->info.read_size == 0); | ||||
|     assert(size % emu->info.read_size == 0); | ||||
|     assert((uint64_t)block*emu->info.erase_size + off + size | ||||
|             < emu->info.total_size); | ||||
|  | ||||
|     // Zero out buffer for debugging | ||||
|     memset(data, 0, size); | ||||
| @@ -128,12 +128,10 @@ int lfs_emubd_prog(lfs_emubd_t *emu, lfs_block_t block, | ||||
|     const uint8_t *data = buffer; | ||||
|  | ||||
|     // Check if write is valid | ||||
|     if (!(off % emu->info.prog_size == 0 && | ||||
|          size % emu->info.prog_size == 0 && | ||||
|          ((uint64_t)block*emu->info.erase_size + off + size | ||||
|           < emu->info.total_size))) { | ||||
|         return -EINVAL; | ||||
|     } | ||||
|     assert(off % emu->info.prog_size == 0); | ||||
|     assert(size % emu->info.prog_size == 0); | ||||
|     assert((uint64_t)block*emu->info.erase_size + off + size | ||||
|             < emu->info.total_size); | ||||
|  | ||||
|     // Iterate over blocks until enough data is read | ||||
|     while (size > 0) { | ||||
| @@ -177,12 +175,10 @@ int lfs_emubd_erase(lfs_emubd_t *emu, lfs_block_t block, | ||||
|         lfs_off_t off, lfs_size_t size) { | ||||
|  | ||||
|     // Check if erase is valid | ||||
|     if (!(off % emu->info.erase_size == 0 && | ||||
|          size % emu->info.erase_size == 0 && | ||||
|          ((uint64_t)block*emu->info.erase_size + off + size | ||||
|           < emu->info.total_size))) { | ||||
|         return -EINVAL; | ||||
|     } | ||||
|     assert(off % emu->info.erase_size == 0); | ||||
|     assert(size % emu->info.erase_size == 0); | ||||
|     assert((uint64_t)block*emu->info.erase_size + off + size | ||||
|             < emu->info.total_size); | ||||
|  | ||||
|     // Iterate and erase blocks | ||||
|     while (size > 0) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user