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.
This commit is contained in:
Ivan Grokhotkov 2017-05-04 14:49:33 +08:00
parent 1a73b41b10
commit d18157e108

View 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) static int vfs_fat_link(void* ctx, const char* n1, const char* n2)
{ {
prepend_drive_to_path(ctx, n1, n2); vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx;
const size_t copy_buf_size = 4096; _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); 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; errno = ENOMEM;
_lock_release(&fat_ctx->lock);
return -1; return -1;
} }
FIL f1; res = f_open(pf1, n1, FA_READ | FA_OPEN_EXISTING);
FRESULT res = f_open(&f1, n1, FA_READ | FA_OPEN_EXISTING);
if (res != FR_OK) { if (res != FR_OK) {
_lock_release(&fat_ctx->lock);
goto fail1; goto fail1;
} }
FIL f2; res = f_open(pf2, n2, FA_WRITE | FA_CREATE_NEW);
res = f_open(&f2, n2, FA_WRITE | FA_CREATE_NEW);
if (res != FR_OK) { if (res != FR_OK) {
_lock_release(&fat_ctx->lock);
goto fail2; 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) { while (size_left > 0) {
size_t will_copy = (size_left < copy_buf_size) ? size_left : copy_buf_size; size_t will_copy = (size_left < copy_buf_size) ? size_left : copy_buf_size;
size_t read; size_t read;
res = f_read(&f1, buf, will_copy, &read); res = f_read(pf1, buf, will_copy, &read);
if (res != FR_OK) { if (res != FR_OK) {
goto fail3; goto fail3;
} else if (read != will_copy) { } else if (read != will_copy) {
@ -453,7 +464,7 @@ static int vfs_fat_link(void* ctx, const char* n1, const char* n2)
goto fail3; goto fail3;
} }
size_t written; size_t written;
res = f_write(&f2, buf, will_copy, &written); res = f_write(pf2, buf, will_copy, &written);
if (res != FR_OK) { if (res != FR_OK) {
goto fail3; goto fail3;
} else if (written != will_copy) { } 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; size_left -= will_copy;
} }
fail3: fail3:
f_close(&f2); f_close(pf2);
free(pf2);
fail2: fail2:
f_close(&f1); f_close(pf1);
free(pf1);
fail1: fail1:
free(buf); free(buf);
if (res != FR_OK) { if (res != FR_OK) {