mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'fix/fatfs_locking' into 'master'
fix(storage/fatfs): add missing locks in fatfs wrapper for vfs Closes IDF-8282 See merge request espressif/esp-idf!26747
This commit is contained in:
commit
38ee8c6373
@ -245,4 +245,12 @@ menu "FAT Filesystem support"
|
||||
default n
|
||||
help
|
||||
Allows FATFS volume label to be specified using f_setlabel
|
||||
|
||||
config FATFS_LINK_LOCK
|
||||
bool "Perform the whole link operation under lock"
|
||||
default y
|
||||
help
|
||||
If enabled, the whole link operation (including file copying) is performed under lock.
|
||||
This ensures that the link operation is atomic, but may cause perfomance for large files.
|
||||
It may create less fragmented file copy.
|
||||
endmenu
|
||||
|
@ -396,10 +396,12 @@ static ssize_t vfs_fat_write(void* ctx, int fd, const void * data, size_t size)
|
||||
vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx;
|
||||
FIL* file = &fat_ctx->files[fd];
|
||||
FRESULT res;
|
||||
_lock_acquire(&fat_ctx->lock);
|
||||
if (fat_ctx->o_append[fd]) {
|
||||
if ((res = f_lseek(file, f_size(file))) != FR_OK) {
|
||||
ESP_LOGD(TAG, "%s: fresult=%d", __func__, res);
|
||||
errno = fresult_to_errno(res);
|
||||
_lock_release(&fat_ctx->lock);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -407,18 +409,19 @@ static ssize_t vfs_fat_write(void* ctx, int fd, const void * data, size_t size)
|
||||
res = f_write(file, data, size, &written);
|
||||
if (((written == 0) && (size != 0)) && (res == 0)) {
|
||||
errno = ENOSPC;
|
||||
_lock_release(&fat_ctx->lock);
|
||||
return -1;
|
||||
}
|
||||
if (res != FR_OK) {
|
||||
ESP_LOGD(TAG, "%s: fresult=%d", __func__, res);
|
||||
errno = fresult_to_errno(res);
|
||||
if (written == 0) {
|
||||
_lock_release(&fat_ctx->lock);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG_FATFS_IMMEDIATE_FSYNC
|
||||
_lock_acquire(&fat_ctx->lock);
|
||||
if (written > 0) {
|
||||
res = f_sync(file);
|
||||
if (res != FR_OK) {
|
||||
@ -428,9 +431,8 @@ static ssize_t vfs_fat_write(void* ctx, int fd, const void * data, size_t size)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
_lock_release(&fat_ctx->lock);
|
||||
#endif
|
||||
|
||||
_lock_release(&fat_ctx->lock);
|
||||
return written;
|
||||
}
|
||||
|
||||
@ -549,10 +551,8 @@ pwrite_release:
|
||||
static int vfs_fat_fsync(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];
|
||||
FRESULT res = f_sync(file);
|
||||
_lock_release(&fat_ctx->lock);
|
||||
int rc = 0;
|
||||
if (res != FR_OK) {
|
||||
ESP_LOGD(TAG, "%s: fresult=%d", __func__, res);
|
||||
@ -707,74 +707,85 @@ static int vfs_fat_link(void* ctx, const char* n1, const char* n2)
|
||||
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;
|
||||
|
||||
FRESULT res = FR_OK;
|
||||
int ret = 0;
|
||||
|
||||
FIL* pf1 = (FIL*) ff_memalloc(sizeof(FIL));
|
||||
FIL* pf2 = (FIL*) ff_memalloc(sizeof(FIL));
|
||||
|
||||
const size_t copy_buf_size = fat_ctx->fs.csize;
|
||||
void* buf = ff_memalloc(copy_buf_size);
|
||||
if (buf == NULL || pf1 == NULL || pf2 == NULL) {
|
||||
_lock_release(&fat_ctx->lock);
|
||||
ESP_LOGD(TAG, "alloc failed, pf1=%p, pf2=%p, buf=%p", pf1, pf2, buf);
|
||||
free(pf1);
|
||||
free(pf2);
|
||||
free(buf);
|
||||
_lock_release(&fat_ctx->lock);
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
memset(pf1, 0, sizeof(*pf1));
|
||||
memset(pf2, 0, sizeof(*pf2));
|
||||
|
||||
res = f_open(pf1, n1, FA_READ | FA_OPEN_EXISTING);
|
||||
if (res != FR_OK) {
|
||||
_lock_release(&fat_ctx->lock);
|
||||
goto fail1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
res = f_open(pf2, n2, FA_WRITE | FA_CREATE_NEW);
|
||||
|
||||
#if !CONFIG_FATFS_LINK_LOCK
|
||||
_lock_release(&fat_ctx->lock);
|
||||
#endif
|
||||
|
||||
if (res != FR_OK) {
|
||||
goto fail2;
|
||||
goto close_old;
|
||||
}
|
||||
|
||||
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(pf1, buf, will_copy, &read);
|
||||
if (res != FR_OK) {
|
||||
goto fail3;
|
||||
goto close_both;
|
||||
} else if (read != will_copy) {
|
||||
res = FR_DISK_ERR;
|
||||
goto fail3;
|
||||
goto close_both;
|
||||
}
|
||||
size_t written;
|
||||
res = f_write(pf2, buf, will_copy, &written);
|
||||
if (res != FR_OK) {
|
||||
goto fail3;
|
||||
goto close_both;
|
||||
} else if (written != will_copy) {
|
||||
res = FR_DISK_ERR;
|
||||
goto fail3;
|
||||
goto close_both;
|
||||
}
|
||||
size_left -= will_copy;
|
||||
}
|
||||
|
||||
#if CONFIG_FATFS_IMMEDIATE_FSYNC
|
||||
_lock_acquire(&fat_ctx->lock);
|
||||
res = f_sync(pf2);
|
||||
close_both:
|
||||
f_close(pf2);
|
||||
|
||||
close_old:
|
||||
f_close(pf1);
|
||||
|
||||
#if CONFIG_FATFS_LINK_LOCK
|
||||
_lock_release(&fat_ctx->lock);
|
||||
#endif
|
||||
|
||||
fail3:
|
||||
f_close(pf2);
|
||||
fail2:
|
||||
f_close(pf1);
|
||||
fail1:
|
||||
cleanup:
|
||||
free(buf);
|
||||
free(pf2);
|
||||
free(pf1);
|
||||
if (res != FR_OK) {
|
||||
if (ret == 0 && res != FR_OK) {
|
||||
ESP_LOGD(TAG, "%s: fresult=%d", __func__, res);
|
||||
errno = fresult_to_errno(res);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vfs_fat_rename(void* ctx, const char *src, const char *dst)
|
||||
@ -881,8 +892,10 @@ static long vfs_fat_telldir(void* ctx, DIR* pdir)
|
||||
static void vfs_fat_seekdir(void* ctx, DIR* pdir, long offset)
|
||||
{
|
||||
assert(pdir);
|
||||
vfs_fat_ctx_t* fat_ctx = (vfs_fat_ctx_t*) ctx;
|
||||
vfs_fat_dir_t* fat_dir = (vfs_fat_dir_t*) pdir;
|
||||
FRESULT res;
|
||||
_lock_acquire(&fat_ctx->lock);
|
||||
if (offset < fat_dir->offset) {
|
||||
res = f_rewinddir(&fat_dir->ffdir);
|
||||
if (res != FR_OK) {
|
||||
@ -901,6 +914,7 @@ static void vfs_fat_seekdir(void* ctx, DIR* pdir, long offset)
|
||||
}
|
||||
fat_dir->offset++;
|
||||
}
|
||||
_lock_release(&fat_ctx->lock);
|
||||
}
|
||||
|
||||
static int vfs_fat_mkdir(void* ctx, const char* name, mode_t mode)
|
||||
|
Loading…
Reference in New Issue
Block a user