From a3734eeb34e09b85b59b53944f88b0325b968488 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sat, 1 Apr 2017 12:23:15 -0500 Subject: 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. --- emubd/lfs_emubd.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) (limited to 'emubd') diff --git a/emubd/lfs_emubd.c b/emubd/lfs_emubd.c index b24cb0a..7acd8f7 100644 --- a/emubd/lfs_emubd.c +++ b/emubd/lfs_emubd.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include // 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) { -- cgit v1.2.3