From b965f5b82b134bc8bfecf6e2a526db1716a5017d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrik=20Dahlstr=C3=B6m?= Date: Sat, 19 Jun 2021 01:05:48 +0200 Subject: [PATCH] make it even more asynchronous This change makes afatfs_poll() an internal static function, and everything else works (almost) as before. The one difference is that callbacks may be called directly from the routine where it was provided, even before the routine returns. E.g. the callback for "unlink complete" may be called before afatfs_funlink() returns. --- lib/asyncfatfs.c | 55 ++++++++++++++++++++++++++++---- lib/asyncfatfs.h | 1 - tests/sdcard_sim.c | 4 +-- tests/test_file_delete.c | 30 ++++++++++------- tests/test_file_modes.c | 2 +- tests/test_file_size.c | 4 +-- tests/test_file_size_powerloss.c | 4 +-- tests/test_logging_workload.c | 2 +- tests/test_root_fill.c | 2 +- tests/test_subdir_fill.c | 2 +- tests/test_volume_fill.c | 2 +- 11 files changed, 77 insertions(+), 31 deletions(-) diff --git a/lib/asyncfatfs.c b/lib/asyncfatfs.c index 37002e7..8c31771 100644 --- a/lib/asyncfatfs.c +++ b/lib/asyncfatfs.c @@ -490,6 +490,8 @@ static afatfs_t afatfs; static void afatfs_fileOperationContinue(afatfsFile_t *file); static uint8_t* afatfs_fileLockCursorSectorForWrite(afatfsFilePtr_t file); static uint8_t* afatfs_fileRetainCursorSectorForRead(afatfsFilePtr_t file); +static void afatfs_fileOperationsPoll(); +static void afatfs_poll(); static uint32_t roundUpTo(uint32_t value, uint32_t rounding) { @@ -639,6 +641,7 @@ static void afatfs_sdcardReadComplete(sdcardBlockOperation_e operation, uint32_t break; } } + afatfs_poll(); } /** @@ -670,6 +673,7 @@ static void afatfs_sdcardWriteComplete(sdcardBlockOperation_e operation, uint32_ break; } } + afatfs_poll(); } /** @@ -904,6 +908,7 @@ static afatfsOperationStatus_e afatfs_cacheSector(uint32_t physicalSectorIndex, if (cacheSectorIndex == -1) { // We don't have enough free cache to service this request right now, try again later + afatfs_flush(); return AFATFS_OPERATION_IN_PROGRESS; } @@ -1454,7 +1459,7 @@ static afatfsOperationStatus_e afatfs_saveDirectoryEntry(afatfsFilePtr_t file, a entry->fileSize = file->physicalSize; break; case AFATFS_SAVE_DIRECTORY_DELETED: - entry->filename[0] = FAT_DELETED_FILE_MARKER; + entry->filename[0] = (char)FAT_DELETED_FILE_MARKER; //Fall through case AFATFS_SAVE_DIRECTORY_FOR_CLOSE: @@ -1560,6 +1565,9 @@ static afatfsOperationStatus_e afatfs_appendRegularFreeClusterContinue(afatfsFil file->operation.operation = AFATFS_FILE_OPERATION_NONE; } + // flush any pending writes + afatfs_flush(); + return AFATFS_OPERATION_SUCCESS; break; case AFATFS_APPEND_FREE_CLUSTER_PHASE_FAILURE: @@ -2054,7 +2062,13 @@ static afatfsOperationStatus_e afatfs_fseekInternal(afatfsFilePtr_t file, uint32 opState->callback = callback; opState->seekOffset = offset; - return AFATFS_OPERATION_IN_PROGRESS; + // Do an initial round of processing + if (afatfs_fseekInternalContinue(file)) { + return AFATFS_OPERATION_SUCCESS; + } + else { + return AFATFS_OPERATION_IN_PROGRESS; + } } } @@ -2262,6 +2276,9 @@ static afatfsOperationStatus_e afatfs_extendSubdirectoryContinue(afatfsFile_t *d opState->callback(directory); } + // flush any pending writes + afatfs_flush(); + return AFATFS_OPERATION_SUCCESS; break; case AFATFS_EXTEND_SUBDIRECTORY_PHASE_FAILURE: @@ -2475,6 +2492,9 @@ static afatfsOperationStatus_e afatfs_ftruncateContinue(afatfsFilePtr_t file, bo opState->callback(file); } + // flush any pending writes + afatfs_flush(); + return AFATFS_OPERATION_SUCCESS; break; } @@ -2677,6 +2697,9 @@ static void afatfs_createFileContinue(afatfsFile_t *file) } } + // flush any pending writes + afatfs_flush(); + file->operation.operation = AFATFS_FILE_OPERATION_NONE; opState->callback(file); break; @@ -2742,6 +2765,8 @@ bool afatfs_funlink(afatfsFilePtr_t file, afatfsCallback_t callback) file->operation.operation = AFATFS_FILE_OPERATION_UNLINK; + afatfs_funlinkContinue(file); + return true; } @@ -2795,6 +2820,11 @@ static afatfsFilePtr_t afatfs_createFile(afatfsFilePtr_t file, const char *name, afatfs_createFileContinue(file); + if (file->operation.operation != AFATFS_FILE_OPERATION_CREATE_FILE && file->operation.operation != AFATFS_FILE_OPERATION_NONE) { + // file operation changed - process it + afatfs_fileOperationsPoll(); + } + return file; } @@ -3394,6 +3424,7 @@ static void afatfs_initContinue() afatfs_chdir(NULL); afatfs.initPhase++; + goto doMore; } else { afatfs.lastError = AFATFS_ERROR_BAD_FILESYSTEM_HEADER; afatfs.filesystemState = AFATFS_FILESYSTEM_STATE_FATAL; @@ -3407,9 +3438,19 @@ static void afatfs_initContinue() afatfs_createFile(&afatfs.freeFile, AFATFS_FREESPACE_FILENAME, FAT_FILE_ATTRIBUTE_SYSTEM | FAT_FILE_ATTRIBUTE_READ_ONLY, AFATFS_FILE_MODE_CREATE | AFATFS_FILE_MODE_RETAIN_DIRECTORY, afatfs_freeFileCreated); + if (afatfs.filesystemState != AFATFS_FILESYSTEM_STATE_FATAL + && afatfs.initPhase != AFATFS_INITIALIZATION_FREEFILE_CREATING + ) { + goto doMore; + } break; case AFATFS_INITIALIZATION_FREEFILE_CREATING: afatfs_fileOperationContinue(&afatfs.freeFile); + if (afatfs.filesystemState != AFATFS_FILESYSTEM_STATE_FATAL + && afatfs.initPhase != AFATFS_INITIALIZATION_FREEFILE_CREATING + ) { + goto doMore; + } break; case AFATFS_INITIALIZATION_FREEFILE_FAT_SEARCH: if (afatfs_findLargestContiguousFreeBlockContinue() == AFATFS_OPERATION_SUCCESS) { @@ -3493,14 +3534,12 @@ static void afatfs_initContinue() /** * Check to see if there are any pending operations on the filesystem and perform a little work (without waiting on the - * sdcard). You must call this periodically. + * sdcard). */ -void afatfs_poll() +static void afatfs_poll() { // Only attempt to continue FS operations if the card is present & ready, otherwise we would just be wasting time - if (sdcard_poll()) { - afatfs_flush(); - + if (sdcard_poll() && afatfs_flush()) { switch (afatfs.filesystemState) { case AFATFS_FILESYSTEM_STATE_INITIALIZATION: afatfs_initContinue(); @@ -3577,6 +3616,8 @@ void afatfs_init() #ifdef AFATFS_USE_INTROSPECTIVE_LOGGING sdcard_setProfilerCallback(afatfs_sdcardProfilerCallback); #endif + + afatfs_poll(); } /** diff --git a/lib/asyncfatfs.h b/lib/asyncfatfs.h index 06659c4..c4b643a 100644 --- a/lib/asyncfatfs.h +++ b/lib/asyncfatfs.h @@ -65,7 +65,6 @@ void afatfs_findLast(afatfsFilePtr_t directory); bool afatfs_flush(); void afatfs_init(); bool afatfs_destroy(bool dirty); -void afatfs_poll(); uint32_t afatfs_getFreeBufferSpace(); uint32_t afatfs_getContiguousFreeSpace(); diff --git a/tests/sdcard_sim.c b/tests/sdcard_sim.c index be9d81e..e721cb0 100644 --- a/tests/sdcard_sim.c +++ b/tests/sdcard_sim.c @@ -80,6 +80,8 @@ static void sdcard_continueReadBlock() if (--sdcard.currentOperation.countdownTimer <= 0) { uint64_t byteIndex = (uint64_t) sdcard.currentOperation.blockIndex * SDCARD_SIM_BLOCK_SIZE; + sdcard.state = SDCARD_STATE_READY; + fseeko(simFile, byteIndex, SEEK_SET); if (fread(sdcard.currentOperation.buffer, sizeof(uint8_t), SDCARD_SIM_BLOCK_SIZE, simFile) == SDCARD_SIM_BLOCK_SIZE) { @@ -93,8 +95,6 @@ static void sdcard_continueReadBlock() fprintf(stderr, "SDCardSim: fread failed on underlying file\n"); exit(-1); } - - sdcard.state = SDCARD_STATE_READY; } } diff --git a/tests/test_file_delete.c b/tests/test_file_delete.c index e5fb23d..f7c1ee1 100644 --- a/tests/test_file_delete.c +++ b/tests/test_file_delete.c @@ -182,9 +182,10 @@ bool continueSpaceReclaimTest(bool start) afatfs_fopen("test.txt", "w+", spaceReclaimTestFileCreatedForEmpty); break; case SPACE_RECLAIM_TEST_STAGE_EMPTY_DELETE: - if (afatfs_funlink(testFile, spaceReclaimTestFileEmptyDeleted)) { - // Wait for the unlink to complete - reclaimTestStage = SPACE_RECLAIM_TEST_STAGE_IDLE; + reclaimTestStage = SPACE_RECLAIM_TEST_STAGE_IDLE; + if (!afatfs_funlink(testFile, spaceReclaimTestFileEmptyDeleted)) { + // retry later + reclaimTestStage = SPACE_RECLAIM_TEST_STAGE_EMPTY_DELETE; } break; case SPACE_RECLAIM_TEST_STAGE_SOLID_APPEND_INIT: @@ -204,9 +205,10 @@ bool continueSpaceReclaimTest(bool start) } break; case SPACE_RECLAIM_TEST_STAGE_SOLID_APPEND_DELETE: - if (afatfs_funlink(testFile, spaceReclaimTestFileSolidAppendDeleted)) { - // Wait for the unlink to complete - reclaimTestStage = SPACE_RECLAIM_TEST_STAGE_IDLE; + reclaimTestStage = SPACE_RECLAIM_TEST_STAGE_IDLE; + if (!afatfs_funlink(testFile, spaceReclaimTestFileSolidAppendDeleted)) { + // retry later + reclaimTestStage = SPACE_RECLAIM_TEST_STAGE_SOLID_APPEND_DELETE; } break; case SPACE_RECLAIM_TEST_STAGE_APPEND_INIT: @@ -226,9 +228,10 @@ bool continueSpaceReclaimTest(bool start) } break; case SPACE_RECLAIM_TEST_STAGE_APPEND_DELETE: - if (afatfs_funlink(testFile, spaceReclaimTestFileAppendDeleted)) { - // Wait for the unlink to complete - reclaimTestStage = SPACE_RECLAIM_TEST_STAGE_IDLE; + reclaimTestStage = SPACE_RECLAIM_TEST_STAGE_IDLE; + if (!afatfs_funlink(testFile, spaceReclaimTestFileAppendDeleted)) { + // retry later + reclaimTestStage = SPACE_RECLAIM_TEST_STAGE_APPEND_DELETE; } break; case SPACE_RECLAIM_TEST_STAGE_IDLE: @@ -392,8 +395,11 @@ bool continueSpaceRetainTest(bool start, const char *fileMode) break; case SPACE_RETAIN_TEST_STAGE_UNLINK_B: if (afatfs_funlink(retainTestFileB, retainTestFileBDeleted)) { - retainTestFileB = NULL; - retainTestStage = SPACE_RETAIN_TEST_STAGE_IDLE; + // need to check state again in case callback has already been triggered + if (retainTestStage == SPACE_RETAIN_TEST_STAGE_UNLINK_B) { + retainTestFileB = NULL; + retainTestStage = SPACE_RETAIN_TEST_STAGE_IDLE; + } } break; case SPACE_RETAIN_TEST_STAGE_VERIFY_A_OPEN: @@ -506,7 +512,7 @@ int main(int argc, char **argv) bool keepGoing = true; while (keepGoing) { - afatfs_poll(); + sdcard_poll(); switch (afatfs_getFilesystemState()) { case AFATFS_FILESYSTEM_STATE_READY: diff --git a/tests/test_file_modes.c b/tests/test_file_modes.c index fc5a6a4..2a9ddec 100644 --- a/tests/test_file_modes.c +++ b/tests/test_file_modes.c @@ -217,7 +217,7 @@ int main(int argc, char **argv) bool keepGoing = true; while (keepGoing) { - afatfs_poll(); + sdcard_poll(); switch (afatfs_getFilesystemState()) { case AFATFS_FILESYSTEM_STATE_READY: diff --git a/tests/test_file_size.c b/tests/test_file_size.c index 8e230ff..f9a58b5 100644 --- a/tests/test_file_size.c +++ b/tests/test_file_size.c @@ -57,7 +57,7 @@ static void initFilesystem() afatfs_init(); while (afatfs_getFilesystemState() != AFATFS_FILESYSTEM_STATE_READY) { - afatfs_poll(); + sdcard_poll(); if (afatfs_getFilesystemState() == AFATFS_FILESYSTEM_STATE_FATAL) { fprintf(stderr, "[Fail] Fatal filesystem error during init\n"); @@ -252,7 +252,7 @@ int main(int argc, char **argv) bool keepGoing = true; while (keepGoing) { - afatfs_poll(); + sdcard_poll(); switch (afatfs_getFilesystemState()) { case AFATFS_FILESYSTEM_STATE_READY: diff --git a/tests/test_file_size_powerloss.c b/tests/test_file_size_powerloss.c index 6d1d236..7c25b26 100644 --- a/tests/test_file_size_powerloss.c +++ b/tests/test_file_size_powerloss.c @@ -58,7 +58,7 @@ static void initFilesystem() afatfs_init(); while (afatfs_getFilesystemState() != AFATFS_FILESYSTEM_STATE_READY) { - afatfs_poll(); + sdcard_poll(); if (afatfs_getFilesystemState() == AFATFS_FILESYSTEM_STATE_FATAL) { fprintf(stderr, "[Fail] Fatal filesystem error during init\n"); @@ -248,7 +248,7 @@ int main(int argc, char **argv) bool keepGoing = true; while (keepGoing) { - afatfs_poll(); + sdcard_poll(); switch (afatfs_getFilesystemState()) { case AFATFS_FILESYSTEM_STATE_READY: diff --git a/tests/test_logging_workload.c b/tests/test_logging_workload.c index f28f3dd..12a7484 100644 --- a/tests/test_logging_workload.c +++ b/tests/test_logging_workload.c @@ -207,7 +207,7 @@ int main(int argc, char **argv) bool keepGoing = true; while (keepGoing) { - afatfs_poll(); + sdcard_poll(); switch (afatfs_getFilesystemState()) { case AFATFS_FILESYSTEM_STATE_READY: diff --git a/tests/test_root_fill.c b/tests/test_root_fill.c index 681e348..c2dbbae 100644 --- a/tests/test_root_fill.c +++ b/tests/test_root_fill.c @@ -134,7 +134,7 @@ int main(int argc, char **argv) bool keepGoing = true; while (keepGoing) { - afatfs_poll(); + sdcard_poll(); switch (afatfs_getFilesystemState()) { case AFATFS_FILESYSTEM_STATE_READY: diff --git a/tests/test_subdir_fill.c b/tests/test_subdir_fill.c index 34e5538..02224a0 100644 --- a/tests/test_subdir_fill.c +++ b/tests/test_subdir_fill.c @@ -153,7 +153,7 @@ int main(int argc, char **argv) bool keepGoing = true; while (keepGoing) { - afatfs_poll(); + sdcard_poll(); switch (afatfs_getFilesystemState()) { case AFATFS_FILESYSTEM_STATE_READY: diff --git a/tests/test_volume_fill.c b/tests/test_volume_fill.c index 126b8b8..dc31f7e 100644 --- a/tests/test_volume_fill.c +++ b/tests/test_volume_fill.c @@ -218,7 +218,7 @@ int main(int argc, char **argv) bool keepGoing = true; while (keepGoing) { - afatfs_poll(); + sdcard_poll(); switch (afatfs_getFilesystemState()) { case AFATFS_FILESYSTEM_STATE_READY: