diff --git a/drivers/block/disk/include/disk.h b/drivers/block/disk/include/disk.h index b1f6884b7309caf6e57acfe8af8ecd577eff41b7..123d6aa3051d342dfa81fc2e1391d2119b36e20b 100644 --- a/drivers/block/disk/include/disk.h +++ b/drivers/block/disk/include/disk.h @@ -165,6 +165,10 @@ extern "C" { #define DISK_ATA_GET_MODEL 21 /* Get model name */ #define DISK_ATA_GET_SN 22 /* Get serial number */ +#ifdef LOSCFG_FS_FAT_CACHE +#define DISK_DIRECT_BUFFER_SIZE 4 /* los_disk direct io buffer when bcache is off */ +#endif + typedef enum _disk_status_ { STAT_UNUSED, STAT_INUSED, @@ -187,6 +191,9 @@ typedef struct _los_disk_ { CHAR *disk_name; LOS_DL_LIST head; /* link head of all the partitions */ struct pthread_mutex disk_mutex; +#ifndef LOSCFG_FS_FAT_CACHE + UINT8 *buff; +#endif } los_disk; typedef struct _los_part_ { diff --git a/drivers/block/disk/src/disk.c b/drivers/block/disk/src/disk.c index 6bec0eac7e4ea0327e35d09e14fa2c1292bf16ce..3fa6b0dd49d16d53ed8c0faf8aa3378d32deb113 100644 --- a/drivers/block/disk/src/disk.c +++ b/drivers/block/disk/src/disk.c @@ -36,6 +36,10 @@ #include "sys/mount.h" #include "linux/spinlock.h" #include "path_cache.h" +#ifndef LOSCFG_FS_FAT_CACHE +#include "los_vm_common.h" +#include "user_copy.h" +#endif los_disk g_sysDisk[SYS_MAX_DISK]; los_part g_sysPart[SYS_MAX_PART]; @@ -799,6 +803,78 @@ INT32 DiskPartitionRegister(los_disk *disk) return ENOERR; } +#ifndef LOSCFG_FS_FAT_CACHE +static INT32 disk_read_directly(los_disk *disk, VOID *buf, UINT64 sector, UINT32 count) +{ + INT32 result = VFS_ERROR; + struct block_operations *bops = (struct block_operations *)((struct drv_data *)disk->dev->data)->ops; + if ((bops == NULL) || (bops->read == NULL)) { + return VFS_ERROR; + } + if (LOS_IsUserAddressRange((VADDR_T)buf, count * disk->sector_size)) { + UINT32 cnt = 0; + UINT8 *buffer = disk->buff; + for (; count != 0; count -= cnt) { + cnt = (count > DISK_DIRECT_BUFFER_SIZE) ? DISK_DIRECT_BUFFER_SIZE : count; + result = bops->read(disk->dev, buffer, sector, cnt); + if (result == (INT32)cnt) { + result = ENOERR; + } else { + break; + } + if (LOS_CopyFromKernel(buf, disk->sector_size * cnt, buffer, disk->sector_size * cnt)) { + result = VFS_ERROR; + break; + } + buf = (UINT8 *)buf + disk->sector_size * cnt; + sector += cnt; + } + } else { + result = bops->read(disk->dev, buf, sector, count); + if (result == count) { + result = ENOERR; + } + } + + return result; +} + +static INT32 disk_write_directly(los_disk *disk, const VOID *buf, UINT64 sector, UINT32 count) +{ + struct block_operations *bops = (struct block_operations *)((struct drv_data *)disk->dev->data)->ops; + INT32 result = VFS_ERROR; + if ((bops == NULL) || (bops->read == NULL)) { + return VFS_ERROR; + } + if (LOS_IsUserAddressRange((VADDR_T)buf, count * disk->sector_size)) { + UINT32 cnt = 0; + UINT8 *buffer = disk->buff; + for (; count != 0; count -= cnt) { + cnt = (count > DISK_DIRECT_BUFFER_SIZE) ? DISK_DIRECT_BUFFER_SIZE : count; + if (LOS_CopyToKernel(buffer, disk->sector_size * cnt, buf, disk->sector_size * cnt)) { + result = VFS_ERROR; + break; + } + result = bops->write(disk->dev, buffer, sector, cnt); + if (result == (INT32)cnt) { + result = ENOERR; + } else { + break; + } + buf = (UINT8 *)buf + disk->sector_size * cnt; + sector += cnt; + } + } else { + result = bops->write(disk->dev, buf, sector, count); + if (result == count) { + result = ENOERR; + } + } + + return result; +} +#endif + INT32 los_disk_read(INT32 drvID, VOID *buf, UINT64 sector, UINT32 count, BOOL useRead) { #ifdef LOSCFG_FS_FAT_CACHE @@ -837,21 +913,14 @@ INT32 los_disk_read(INT32 drvID, VOID *buf, UINT64 sector, UINT32 count, BOOL us PRINT_ERR("los_disk_read read err = %d, sector = %llu, len = %u\n", result, sector, len); } } else { -#endif + result = VFS_ERROR; + } +#else if (disk->dev == NULL) { goto ERROR_HANDLE; } - struct block_operations *bops = (struct block_operations *)((struct drv_data *)disk->dev->data)->ops; - if ((bops != NULL) && (bops->read != NULL)) { - result = bops->read(disk->dev, (UINT8 *)buf, sector, count); - if (result == (INT32)count) { - result = ENOERR; - } - } -#ifdef LOSCFG_FS_FAT_CACHE - } + result = disk_read_directly(disk, buf, sector, count); #endif - if (result != ENOERR) { goto ERROR_HANDLE; } @@ -900,18 +969,14 @@ INT32 los_disk_write(INT32 drvID, const VOID *buf, UINT64 sector, UINT32 count) PRINT_ERR("los_disk_write write err = %d, sector = %llu, len = %u\n", result, sector, len); } } else { -#endif - struct block_operations *bops = (struct block_operations *)((struct drv_data *)disk->dev->data)->ops; - if ((bops != NULL) && (bops->write != NULL)) { - result = bops->write(disk->dev, (UINT8 *)buf, sector, count); - if (result == (INT32)count) { - result = ENOERR; - } + result = VFS_ERROR; } -#ifdef LOSCFG_FS_FAT_CACHE +#else + if (disk->dev == NULL) { + goto ERROR_HANDLE; } + result = disk_write_directly(disk, buf, sector, count); #endif - if (result != ENOERR) { goto ERROR_HANDLE; } @@ -1153,7 +1218,8 @@ ERROR_HANDLE: INT32 los_disk_cache_clear(INT32 drvID) { - INT32 result; + INT32 result = ENOERR; +#ifdef LOSCFG_FS_FAT_CACHE los_part *part = get_part(drvID); los_disk *disk = NULL; @@ -1161,7 +1227,7 @@ INT32 los_disk_cache_clear(INT32 drvID) return VFS_ERROR; } result = OsSdSync(part->disk_id); - if (result != 0) { + if (result != ENOERR) { PRINTK("[ERROR]disk_cache_clear SD sync failed!\n"); return result; } @@ -1174,7 +1240,7 @@ INT32 los_disk_cache_clear(INT32 drvID) DISK_LOCK(&disk->disk_mutex); result = BcacheClearCache(disk->bcache); DISK_UNLOCK(&disk->disk_mutex); - +#endif return result; } @@ -1324,6 +1390,10 @@ static INT32 DiskDeinit(los_disk *disk) #ifdef LOSCFG_FS_FAT_CACHE DiskCacheDeinit(disk); +#else + if (disk->buff != NULL) { + free(disk->buff); + } #endif disk->dev = NULL; @@ -1344,12 +1414,15 @@ static INT32 DiskDeinit(los_disk *disk) return ENOERR; } -static VOID OsDiskInitSub(const CHAR *diskName, INT32 diskID, los_disk *disk, - struct geometry *diskInfo, struct Vnode *blkDriver) +static UINT32 OsDiskInitSub(const CHAR *diskName, INT32 diskID, los_disk *disk, + struct geometry *diskInfo, struct Vnode *blkDriver) { pthread_mutexattr_t attr; #ifdef LOSCFG_FS_FAT_CACHE OsBcache *bc = DiskCacheInit((UINT32)diskID, diskInfo, blkDriver); + if (bc == NULL) { + return VFS_ERROR; + } disk->bcache = bc; #endif @@ -1358,6 +1431,16 @@ static VOID OsDiskInitSub(const CHAR *diskName, INT32 diskID, los_disk *disk, (VOID)pthread_mutex_init(&disk->disk_mutex, &attr); DiskStructInit(diskName, diskID, diskInfo, blkDriver, disk); + +#ifndef LOSCFG_FS_FAT_CACHE + disk->buff = malloc(diskInfo->geo_sectorsize * DISK_DIRECT_BUFFER_SIZE); + if (disk->buff == NULL) { + PRINT_ERR("OsDiskInitSub: direct buffer of disk init failed\n"); + return VFS_ERROR; + } +#endif + + return ENOERR; } INT32 los_disk_init(const CHAR *diskName, const struct block_operations *bops, @@ -1382,14 +1465,12 @@ INT32 los_disk_init(const CHAR *diskName, const struct block_operations *bops, ret = VnodeLookup(diskName, &blkDriver, 0); if (ret < 0) { VnodeDrop(); - PRINT_ERR("disk_init : find %s fail!\n", diskName); ret = ENOENT; goto DISK_FIND_ERROR; } struct block_operations *bops2 = (struct block_operations *)((struct drv_data *)blkDriver->data)->ops; - if ((bops2 == NULL) || (bops2->geometry == NULL) || - (bops2->geometry(blkDriver, &diskInfo) != 0)) { + if ((bops2 == NULL) || (bops2->geometry == NULL) || (bops2->geometry(blkDriver, &diskInfo) != 0)) { goto DISK_BLKDRIVER_ERROR; } @@ -1397,7 +1478,12 @@ INT32 los_disk_init(const CHAR *diskName, const struct block_operations *bops, goto DISK_BLKDRIVER_ERROR; } - OsDiskInitSub(diskName, diskID, disk, &diskInfo, blkDriver); + ret = OsDiskInitSub(diskName, diskID, disk, &diskInfo, blkDriver); + if (ret != ENOERR) { + (VOID)DiskDeinit(disk); + VnodeDrop(); + return VFS_ERROR; + } VnodeDrop(); if (DiskDivideAndPartitionRegister(info, disk) != ENOERR) { (VOID)DiskDeinit(disk); diff --git a/fs/fat/os_adapt/fatfs.c b/fs/fat/os_adapt/fatfs.c index d8bf81b84f16973ceb203746b997ccbc022ccbb7..000881277821db7d2a7d2ac444b769410399a4ae 100644 --- a/fs/fat/os_adapt/fatfs.c +++ b/fs/fat/os_adapt/fatfs.c @@ -2053,45 +2053,18 @@ static UINT get_oldest_time(DIR_FILE df[], DWORD *oldest_time, UINT len) return index; } -int fatfs_fscheck(struct Vnode* vp, struct fs_dirent_s *dir) +static FRESULT fscheck(DIR *dp) { - FATFS *fs = (FATFS *)vp->originMount->data; DIR_FILE df[CHECK_FILE_NUM] = {0}; - DIR *dp = NULL; - FILINFO *finfo = &(((DIR_FILE *)(vp->data))->fno); FILINFO fno; - DWORD old_time = -1; - DWORD time; - UINT count; UINT index = 0; - los_part *part = NULL; + UINT count; + DWORD time; + DWORD old_time = -1; FRESULT result; - int ret; - - if (fs->fs_type != FS_FAT32) { - return -EINVAL; - } - - if ((finfo->fattrib & AM_DIR) == 0) { - return -ENOTDIR; - } - - ret = fatfs_opendir(vp, dir); - if (ret < 0) { - return ret; - } - - ret = lock_fs(fs); - if (ret == FALSE) { - result = FR_TIMEOUT; - goto ERROR_WITH_DIR; - } - - dp = (DIR *)dir->u.fs_dir; - dp->obj.id = fs->id; for (count = 0; count < CHECK_FILE_NUM; count++) { if ((result = f_readdir(dp, &fno)) != FR_OK) { - goto ERROR_UNLOCK; + return result; } else { if (fno.fname[0] == 0 || fno.fname[0] == (TCHAR)0xFF) { break; @@ -2116,15 +2089,50 @@ int fatfs_fscheck(struct Vnode* vp, struct fs_dirent_s *dir) index = get_oldest_time(df, &old_time, CHECK_FILE_NUM); } } - if (result != FR_OK) { - goto ERROR_UNLOCK; + index = 0; + while (result == FR_OK && index < count) { + result = f_fcheckfat(&df[index]); + ++index; } - for (index = 0; index < count; index++) { - result = f_fcheckfat(&df[index]); - if (result != FR_OK) { - goto ERROR_UNLOCK; - } + return result; +} + +int fatfs_fscheck(struct Vnode* vp, struct fs_dirent_s *dir) +{ + FATFS *fs = (FATFS *)vp->originMount->data; + DIR *dp = NULL; + FILINFO *finfo = &(((DIR_FILE *)(vp->data))->fno); +#ifdef LOSCFG_FS_FAT_CACHE + los_part *part = NULL; +#endif + FRESULT result; + int ret; + + if (fs->fs_type != FS_FAT32) { + return -EINVAL; + } + + if ((finfo->fattrib & AM_DIR) == 0) { + return -ENOTDIR; + } + + ret = fatfs_opendir(vp, dir); + if (ret < 0) { + return ret; + } + + ret = lock_fs(fs); + if (ret == FALSE) { + result = FR_TIMEOUT; + goto ERROR_WITH_DIR; + } + + dp = (DIR *)dir->u.fs_dir; + dp->obj.id = fs->id; + result = fscheck(dp); + if (result != FR_OK) { + goto ERROR_UNLOCK; } unlock_fs(fs, FR_OK);