AP_FileSystem: chunk IOs to max 4k

this prevents larger IOs from attempting to allocate too much memory
in DMA bouncebuffers
This commit is contained in:
Andrew Tridgell 2020-01-17 20:44:53 +11:00
parent 3187a501f7
commit 6d4a4604f2

View File

@ -3,6 +3,7 @@
*/ */
#include "AP_Filesystem.h" #include "AP_Filesystem.h"
#include <AP_HAL/AP_HAL.h> #include <AP_HAL/AP_HAL.h>
#include <AP_Math/AP_Math.h>
#include <stdio.h> #include <stdio.h>
#if HAVE_FILESYSTEM_SUPPORT && CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS #if HAVE_FILESYSTEM_SUPPORT && CONFIG_HAL_BOARD == HAL_BOARD_CHIBIOS
@ -23,6 +24,10 @@ static bool remount_needed;
#define FATFS_W (S_IWUSR | S_IWGRP | S_IWOTH) /*< FatFs Write perms */ #define FATFS_W (S_IWUSR | S_IWGRP | S_IWOTH) /*< FatFs Write perms */
#define FATFS_X (S_IXUSR | S_IXGRP | S_IXOTH) /*< FatFs Execute perms */ #define FATFS_X (S_IXUSR | S_IXGRP | S_IXOTH) /*< FatFs Execute perms */
// don't write more than 4k at a time to prevent needing too much
// DMAable memory
#define MAX_IO_SIZE 4096
// use a semaphore to ensure that only one filesystem operation is // use a semaphore to ensure that only one filesystem operation is
// happening at a time. A recursive semaphore is used to cope with the // happening at a time. A recursive semaphore is used to cope with the
// mkdir() inside sdcard_retry() // mkdir() inside sdcard_retry()
@ -379,7 +384,6 @@ int AP_Filesystem::close(int fileno)
ssize_t AP_Filesystem::read(int fd, void *buf, size_t count) ssize_t AP_Filesystem::read(int fd, void *buf, size_t count)
{ {
UINT size;
UINT bytes = count; UINT bytes = count;
int res; int res;
FIL *fh; FIL *fh;
@ -401,17 +405,31 @@ ssize_t AP_Filesystem::read(int fd, void *buf, size_t count)
return -1; return -1;
} }
res = f_read(fh, (void *) buf, bytes, &size); UINT total = 0;
if (res != FR_OK) { do {
errno = fatfs_to_errno((FRESULT)res); UINT size = 0;
return -1; UINT n = MIN(bytes, MAX_IO_SIZE);
} res = f_read(fh, (void *)buf, n, &size);
return (ssize_t)size; if (res != FR_OK) {
errno = fatfs_to_errno((FRESULT)res);
return -1;
}
if (size > n || size == 0) {
errno = EIO;
return -1;
}
total += size;
buf = (void *)(((uint8_t *)buf)+size);
bytes -= size;
if (size < n) {
break;
}
} while (bytes > 0);
return (ssize_t)total;
} }
ssize_t AP_Filesystem::write(int fd, const void *buf, size_t count) ssize_t AP_Filesystem::write(int fd, const void *buf, size_t count)
{ {
UINT size;
UINT bytes = count; UINT bytes = count;
FRESULT res; FRESULT res;
FIL *fh; FIL *fh;
@ -428,19 +446,34 @@ ssize_t AP_Filesystem::write(int fd, const void *buf, size_t count)
return -1; return -1;
} }
res = f_write(fh, buf, bytes, &size); UINT total = 0;
if (res == FR_DISK_ERR && RETRY_ALLOWED()) { do {
// one retry on disk error UINT n = MIN(bytes, MAX_IO_SIZE);
hal.scheduler->delay(100); UINT size = 0;
if (remount_file_system()) { res = f_write(fh, buf, n, &size);
res = f_write(fh, buf, bytes, &size); if (res == FR_DISK_ERR && RETRY_ALLOWED()) {
// one retry on disk error
hal.scheduler->delay(100);
if (remount_file_system()) {
res = f_write(fh, buf, n, &size);
}
} }
} if (size > n || size == 0) {
if (res != FR_OK) { errno = EIO;
errno = fatfs_to_errno(res); return -1;
return -1; }
} if (res != FR_OK || size > n) {
return (ssize_t)size; errno = fatfs_to_errno(res);
return -1;
}
total += size;
buf = (void *)(((uint8_t *)buf)+size);
bytes -= size;
if (size < n) {
break;
}
} while (bytes > 0);
return (ssize_t)total;
} }
int AP_Filesystem::fsync(int fileno) int AP_Filesystem::fsync(int fileno)