]> granicus.if.org Git - esp-idf/commitdiff
vfs_fat: allocate FIL structures on the heap in vfs_fat_link
authorIvan Grokhotkov <ivan@espressif.com>
Thu, 4 May 2017 06:49:33 +0000 (14:49 +0800)
committerIvan Grokhotkov <ivan@espressif.com>
Fri, 5 May 2017 07:21:37 +0000 (15:21 +0800)
vfs_fat_link opened two files to perform copy operation. File structures
were allocated on the stack. When _MAX_SS setting was increased in
ffconf.h due to wear levelling feature, the size of these structures
increased to ~4k each (~8k total). This exceeds stack size allocated for
tasks in most typical cases.

This change makes file structures dynamically allocated.

components/fatfs/src/vfs_fat.c

index 5e4f0fb1aaabbd25bfe852005aba246e804448ae..df2eb4cadf52aaa2d16af53d31c34d667cf61f8a 100644 (file)
@@ -424,28 +424,39 @@ static int vfs_fat_unlink(void* ctx, const char *path)
 
 static int vfs_fat_link(void* ctx, const char* n1, const char* n2)
 {
-    prepend_drive_to_path(ctx, n1, n2);
-    const size_t copy_buf_size = 4096;
+    vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx;
+    _lock_acquire(&fat_ctx->lock);
+    prepend_drive_to_path(fat_ctx, &n1, &n2);
+    const size_t copy_buf_size = fat_ctx->fs.csize;
+    FRESULT res;
+    FIL* pf1 = calloc(1, sizeof(FIL));
+    FIL* pf2 = calloc(1, sizeof(FIL));
     void* buf = malloc(copy_buf_size);
-    if (buf == NULL) {
+    if (buf == NULL || pf1 == NULL || pf2 == NULL) {
+        ESP_LOGD(TAG, "alloc failed, pf1=%p, pf2=%p, buf=%p", pf1, pf2, buf);
+        free(pf1);
+        free(pf2);
+        free(buf);
         errno = ENOMEM;
+        _lock_release(&fat_ctx->lock);
         return -1;
     }
-    FIL f1;
-    FRESULT res = f_open(&f1, n1, FA_READ | FA_OPEN_EXISTING);
+    res = f_open(pf1, n1, FA_READ | FA_OPEN_EXISTING);
     if (res != FR_OK) {
+        _lock_release(&fat_ctx->lock);
         goto fail1;
     }
-    FIL f2;
-    res = f_open(&f2, n2, FA_WRITE | FA_CREATE_NEW);
+    res = f_open(pf2, n2, FA_WRITE | FA_CREATE_NEW);
     if (res != FR_OK) {
+        _lock_release(&fat_ctx->lock);
         goto fail2;
     }
-    size_t size_left = f_size(&f1);
+    _lock_release(&fat_ctx->lock);
+    size_t size_left = f_size(pf1);
     while (size_left > 0) {
         size_t will_copy = (size_left < copy_buf_size) ? size_left : copy_buf_size;
         size_t read;
-        res = f_read(&f1, buf, will_copy, &read);
+        res = f_read(pf1, buf, will_copy, &read);
         if (res != FR_OK) {
             goto fail3;
         } else if (read != will_copy) {
@@ -453,7 +464,7 @@ static int vfs_fat_link(void* ctx, const char* n1, const char* n2)
             goto fail3;
         }
         size_t written;
-        res = f_write(&f2, buf, will_copy, &written);
+        res = f_write(pf2, buf, will_copy, &written);
         if (res != FR_OK) {
             goto fail3;
         } else if (written != will_copy) {
@@ -462,11 +473,12 @@ static int vfs_fat_link(void* ctx, const char* n1, const char* n2)
         }
         size_left -= will_copy;
     }
-
 fail3:
-    f_close(&f2);
+    f_close(pf2);
+    free(pf2);
 fail2:
-    f_close(&f1);
+    f_close(pf1);
+    free(pf1);
 fail1:
     free(buf);
     if (res != FR_OK) {