From: Ivan Grokhotkov Date: Thu, 4 May 2017 06:49:33 +0000 (+0800) Subject: vfs_fat: allocate FIL structures on the heap in vfs_fat_link X-Git-Tag: v2.1-rc1~132^2~5 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d18157e108c15147b8e9d2a00c0fe88aa5b62f36;p=esp-idf vfs_fat: allocate FIL structures on the heap in vfs_fat_link 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. --- diff --git a/components/fatfs/src/vfs_fat.c b/components/fatfs/src/vfs_fat.c index 5e4f0fb1aa..df2eb4cadf 100644 --- a/components/fatfs/src/vfs_fat.c +++ b/components/fatfs/src/vfs_fat.c @@ -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) {