Parcourir la source

fat_vfs: added fast seek capable file operation

Felipe Neves il y a 5 ans
Parent
commit
32e760adfb

+ 12 - 3
components/fatfs/Kconfig

@@ -182,14 +182,23 @@ menu "FAT Filesystem support"
 
 
     config FATFS_USE_FASTSEEK
-        bool "Enable fast seek algorithm when using f_lseek function"
+        bool "Enable fast seek algorithm when using lseek function through VFS FAT"
         default n
         help
             The fast seek feature enables fast backward/long seek operations without
             FAT access by using an in-memory CLMT (cluster link map table).
             It is applied to f_read and f_write function as well, however,
-            the file size cannot be expanded by f_write.
-            f_lseek function while the file is at fast seek mode.
+            the file size cannot be expanded by write function.
 
 
+    config FATFS_FAST_SEEK_BUFFER_SIZE
+        int "Fast seek CLMT buffer size"
+        default 64
+        depends on FATFS_USE_FASTSEEK
+        help
+            If fast seek algorithm is enabled, this defines the size of
+            CLMT buffer used by this algorithm in 32-bit word units.
+            This value should be chosen based on prior knowledge of
+            maximum elements of each file entry would store.
+
 endmenu

+ 37 - 0
components/fatfs/vfs/vfs_fat.c

@@ -307,6 +307,7 @@ static int vfs_fat_open(void* ctx, const char * path, int flags, int mode)
         errno = ENFILE;
         return -1;
     }
+
     FRESULT res = f_open(&fat_ctx->files[fd], path, fat_mode_conv(flags));
     if (res != FR_OK) {
         file_cleanup(fat_ctx, fd);
@@ -315,6 +316,34 @@ static int vfs_fat_open(void* ctx, const char * path, int flags, int mode)
         errno = fresult_to_errno(res);
         return -1;
     }
+
+#ifdef CONFIG_FATFS_USE_FASTSEEK
+    FIL* file = &fat_ctx->files[fd];
+    DWORD *clmt_mem =  ff_memalloc(sizeof(DWORD) * CONFIG_FATFS_FAST_SEEK_BUFFER_SIZE);
+    if (clmt_mem == NULL) {
+        f_close(file);
+        file_cleanup(fat_ctx, fd);
+        _lock_release(&fat_ctx->lock);
+        ESP_LOGE(TAG, "open: Failed to pre-allocate CLMT buffer for fast-seek");
+        errno = ENOMEM;
+        return -1;
+    } 
+
+    file->cltbl = clmt_mem;
+    file->cltbl[0] = CONFIG_FATFS_FAST_SEEK_BUFFER_SIZE;
+    res = f_lseek(file, CREATE_LINKMAP);
+    ESP_LOGD(TAG, "%s: fast-seek has: %s",
+            __func__,
+            (res == FR_OK) ? "activated" : "failed");
+    if(res != FR_OK) {
+        ESP_LOGW(TAG, "%s: fast-seek not activated reason code: %d",
+                __func__, res);
+        //If linkmap creation fails, fallback to the non fast seek.
+        ff_memfree(file->cltbl);
+        file->cltbl = NULL;
+    }
+#endif
+
     // O_APPEND need to be stored because it is not compatible with FA_OPEN_APPEND:
     //  - FA_OPEN_APPEND means to jump to the end of file only after open()
     //  - O_APPEND means to jump to the end only before each write()
@@ -465,6 +494,11 @@ static int vfs_fat_close(void* ctx, int fd)
     vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx;
     _lock_acquire(&fat_ctx->lock);
     FIL* file = &fat_ctx->files[fd];
+
+#ifdef CONFIG_FATFS_USE_FASTSEEK
+    ff_memfree(file->cltbl);
+#endif
+
     FRESULT res = f_close(file);
     file_cleanup(fat_ctx, fd);
     _lock_release(&fat_ctx->lock);
@@ -494,6 +528,9 @@ static off_t vfs_fat_lseek(void* ctx, int fd, off_t offset, int mode)
         errno = EINVAL;
         return -1;
     }
+
+    ESP_LOGD(TAG, "%s: offset=%ld, filesize:=%d", __func__, new_pos, f_size(file));
+
     FRESULT res = f_lseek(file, new_pos);
     if (res != FR_OK) {
         ESP_LOGD(TAG, "%s: fresult=%d", __func__, res);

+ 1 - 0
tools/ci/config/target-test.yml

@@ -345,6 +345,7 @@ UT_002:
 
 UT_003:
   extends: .unit_test_template
+  parallel: 2
   tags:
     - ESP32_IDF
     - UT_T1_SDMODE

+ 3 - 0
tools/unit-test-app/configs/fatfs_fast_seek

@@ -0,0 +1,3 @@
+TEST_COMPONENTS=fatfs
+CONFIG_FATFS_USE_FASTSEEK=y
+CONFIG_FATFS_FAST_SEEK_BUFFER_SIZE=64