fix: 修复LOSCFG_FS_FAT_CACHE宏关闭后编译失败的BUG 1. 在必要处增加宏开关关闭部分代码的编译; 2. 由于驱动是一个独立的内核线程,在一些场景下文件系统会将用户态地址透传给驱动,这会导致内核崩溃。 因此在需要透传用户态地址时增加了一个内核buffer作为中转。 Close #I3T3N0 Signed-off-by: Far <yesiyuan2@huawei.com>
This commit is contained in:
parent
d9752abcb4
commit
332ba8fd65
|
@ -165,6 +165,10 @@ extern "C" {
|
||||||
#define DISK_ATA_GET_MODEL 21 /* Get model name */
|
#define DISK_ATA_GET_MODEL 21 /* Get model name */
|
||||||
#define DISK_ATA_GET_SN 22 /* Get serial number */
|
#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_ {
|
typedef enum _disk_status_ {
|
||||||
STAT_UNUSED,
|
STAT_UNUSED,
|
||||||
STAT_INUSED,
|
STAT_INUSED,
|
||||||
|
@ -187,6 +191,9 @@ typedef struct _los_disk_ {
|
||||||
CHAR *disk_name;
|
CHAR *disk_name;
|
||||||
LOS_DL_LIST head; /* link head of all the partitions */
|
LOS_DL_LIST head; /* link head of all the partitions */
|
||||||
struct pthread_mutex disk_mutex;
|
struct pthread_mutex disk_mutex;
|
||||||
|
#ifndef LOSCFG_FS_FAT_CACHE
|
||||||
|
UINT8 *buff;
|
||||||
|
#endif
|
||||||
} los_disk;
|
} los_disk;
|
||||||
|
|
||||||
typedef struct _los_part_ {
|
typedef struct _los_part_ {
|
||||||
|
|
|
@ -36,6 +36,10 @@
|
||||||
#include "sys/mount.h"
|
#include "sys/mount.h"
|
||||||
#include "linux/spinlock.h"
|
#include "linux/spinlock.h"
|
||||||
#include "path_cache.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_disk g_sysDisk[SYS_MAX_DISK];
|
||||||
los_part g_sysPart[SYS_MAX_PART];
|
los_part g_sysPart[SYS_MAX_PART];
|
||||||
|
@ -799,6 +803,78 @@ INT32 DiskPartitionRegister(los_disk *disk)
|
||||||
return ENOERR;
|
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)
|
INT32 los_disk_read(INT32 drvID, VOID *buf, UINT64 sector, UINT32 count, BOOL useRead)
|
||||||
{
|
{
|
||||||
#ifdef LOSCFG_FS_FAT_CACHE
|
#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);
|
PRINT_ERR("los_disk_read read err = %d, sector = %llu, len = %u\n", result, sector, len);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#endif
|
result = VFS_ERROR;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (disk->dev == NULL) {
|
if (disk->dev == NULL) {
|
||||||
goto ERROR_HANDLE;
|
goto ERROR_HANDLE;
|
||||||
}
|
}
|
||||||
struct block_operations *bops = (struct block_operations *)((struct drv_data *)disk->dev->data)->ops;
|
result = disk_read_directly(disk, buf, sector, count);
|
||||||
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
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (result != ENOERR) {
|
if (result != ENOERR) {
|
||||||
goto ERROR_HANDLE;
|
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);
|
PRINT_ERR("los_disk_write write err = %d, sector = %llu, len = %u\n", result, sector, len);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
result = VFS_ERROR;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (disk->dev == NULL) {
|
||||||
|
goto ERROR_HANDLE;
|
||||||
|
}
|
||||||
|
result = disk_write_directly(disk, buf, sector, count);
|
||||||
#endif
|
#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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef LOSCFG_FS_FAT_CACHE
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (result != ENOERR) {
|
if (result != ENOERR) {
|
||||||
goto ERROR_HANDLE;
|
goto ERROR_HANDLE;
|
||||||
}
|
}
|
||||||
|
@ -1153,7 +1218,8 @@ ERROR_HANDLE:
|
||||||
|
|
||||||
INT32 los_disk_cache_clear(INT32 drvID)
|
INT32 los_disk_cache_clear(INT32 drvID)
|
||||||
{
|
{
|
||||||
INT32 result;
|
INT32 result = ENOERR;
|
||||||
|
#ifdef LOSCFG_FS_FAT_CACHE
|
||||||
los_part *part = get_part(drvID);
|
los_part *part = get_part(drvID);
|
||||||
los_disk *disk = NULL;
|
los_disk *disk = NULL;
|
||||||
|
|
||||||
|
@ -1161,7 +1227,7 @@ INT32 los_disk_cache_clear(INT32 drvID)
|
||||||
return VFS_ERROR;
|
return VFS_ERROR;
|
||||||
}
|
}
|
||||||
result = OsSdSync(part->disk_id);
|
result = OsSdSync(part->disk_id);
|
||||||
if (result != 0) {
|
if (result != ENOERR) {
|
||||||
PRINTK("[ERROR]disk_cache_clear SD sync failed!\n");
|
PRINTK("[ERROR]disk_cache_clear SD sync failed!\n");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1174,7 +1240,7 @@ INT32 los_disk_cache_clear(INT32 drvID)
|
||||||
DISK_LOCK(&disk->disk_mutex);
|
DISK_LOCK(&disk->disk_mutex);
|
||||||
result = BcacheClearCache(disk->bcache);
|
result = BcacheClearCache(disk->bcache);
|
||||||
DISK_UNLOCK(&disk->disk_mutex);
|
DISK_UNLOCK(&disk->disk_mutex);
|
||||||
|
#endif
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1324,6 +1390,10 @@ static INT32 DiskDeinit(los_disk *disk)
|
||||||
|
|
||||||
#ifdef LOSCFG_FS_FAT_CACHE
|
#ifdef LOSCFG_FS_FAT_CACHE
|
||||||
DiskCacheDeinit(disk);
|
DiskCacheDeinit(disk);
|
||||||
|
#else
|
||||||
|
if (disk->buff != NULL) {
|
||||||
|
free(disk->buff);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
disk->dev = NULL;
|
disk->dev = NULL;
|
||||||
|
@ -1344,12 +1414,15 @@ static INT32 DiskDeinit(los_disk *disk)
|
||||||
return ENOERR;
|
return ENOERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID OsDiskInitSub(const CHAR *diskName, INT32 diskID, los_disk *disk,
|
static UINT32 OsDiskInitSub(const CHAR *diskName, INT32 diskID, los_disk *disk,
|
||||||
struct geometry *diskInfo, struct Vnode *blkDriver)
|
struct geometry *diskInfo, struct Vnode *blkDriver)
|
||||||
{
|
{
|
||||||
pthread_mutexattr_t attr;
|
pthread_mutexattr_t attr;
|
||||||
#ifdef LOSCFG_FS_FAT_CACHE
|
#ifdef LOSCFG_FS_FAT_CACHE
|
||||||
OsBcache *bc = DiskCacheInit((UINT32)diskID, diskInfo, blkDriver);
|
OsBcache *bc = DiskCacheInit((UINT32)diskID, diskInfo, blkDriver);
|
||||||
|
if (bc == NULL) {
|
||||||
|
return VFS_ERROR;
|
||||||
|
}
|
||||||
disk->bcache = bc;
|
disk->bcache = bc;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1358,6 +1431,16 @@ static VOID OsDiskInitSub(const CHAR *diskName, INT32 diskID, los_disk *disk,
|
||||||
(VOID)pthread_mutex_init(&disk->disk_mutex, &attr);
|
(VOID)pthread_mutex_init(&disk->disk_mutex, &attr);
|
||||||
|
|
||||||
DiskStructInit(diskName, diskID, diskInfo, blkDriver, disk);
|
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,
|
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);
|
ret = VnodeLookup(diskName, &blkDriver, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
VnodeDrop();
|
VnodeDrop();
|
||||||
PRINT_ERR("disk_init : find %s fail!\n", diskName);
|
|
||||||
ret = ENOENT;
|
ret = ENOENT;
|
||||||
goto DISK_FIND_ERROR;
|
goto DISK_FIND_ERROR;
|
||||||
}
|
}
|
||||||
struct block_operations *bops2 = (struct block_operations *)((struct drv_data *)blkDriver->data)->ops;
|
struct block_operations *bops2 = (struct block_operations *)((struct drv_data *)blkDriver->data)->ops;
|
||||||
|
|
||||||
if ((bops2 == NULL) || (bops2->geometry == NULL) ||
|
if ((bops2 == NULL) || (bops2->geometry == NULL) || (bops2->geometry(blkDriver, &diskInfo) != 0)) {
|
||||||
(bops2->geometry(blkDriver, &diskInfo) != 0)) {
|
|
||||||
goto DISK_BLKDRIVER_ERROR;
|
goto DISK_BLKDRIVER_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1397,7 +1478,12 @@ INT32 los_disk_init(const CHAR *diskName, const struct block_operations *bops,
|
||||||
goto DISK_BLKDRIVER_ERROR;
|
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();
|
VnodeDrop();
|
||||||
if (DiskDivideAndPartitionRegister(info, disk) != ENOERR) {
|
if (DiskDivideAndPartitionRegister(info, disk) != ENOERR) {
|
||||||
(VOID)DiskDeinit(disk);
|
(VOID)DiskDeinit(disk);
|
||||||
|
|
|
@ -2033,45 +2033,18 @@ static UINT get_oldest_time(DIR_FILE df[], DWORD *oldest_time, UINT len)
|
||||||
return index;
|
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_FILE df[CHECK_FILE_NUM] = {0};
|
||||||
DIR *dp = NULL;
|
|
||||||
FILINFO *finfo = &(((DIR_FILE *)(vp->data))->fno);
|
|
||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
DWORD old_time = -1;
|
|
||||||
DWORD time;
|
|
||||||
UINT count;
|
|
||||||
UINT index = 0;
|
UINT index = 0;
|
||||||
los_part *part = NULL;
|
UINT count;
|
||||||
|
DWORD time;
|
||||||
|
DWORD old_time = -1;
|
||||||
FRESULT result;
|
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++) {
|
for (count = 0; count < CHECK_FILE_NUM; count++) {
|
||||||
if ((result = f_readdir(dp, &fno)) != FR_OK) {
|
if ((result = f_readdir(dp, &fno)) != FR_OK) {
|
||||||
goto ERROR_UNLOCK;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
if (fno.fname[0] == 0 || fno.fname[0] == (TCHAR)0xFF) {
|
if (fno.fname[0] == 0 || fno.fname[0] == (TCHAR)0xFF) {
|
||||||
break;
|
break;
|
||||||
|
@ -2096,16 +2069,51 @@ int fatfs_fscheck(struct Vnode* vp, struct fs_dirent_s *dir)
|
||||||
index = get_oldest_time(df, &old_time, CHECK_FILE_NUM);
|
index = get_oldest_time(df, &old_time, CHECK_FILE_NUM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result != FR_OK) {
|
index = 0;
|
||||||
goto ERROR_UNLOCK;
|
while (result == FR_OK && index < count) {
|
||||||
|
result = f_fcheckfat(&df[index]);
|
||||||
|
++index;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (index = 0; index < count; index++) {
|
return result;
|
||||||
result = f_fcheckfat(&df[index]);
|
}
|
||||||
|
|
||||||
|
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) {
|
if (result != FR_OK) {
|
||||||
goto ERROR_UNLOCK;
|
goto ERROR_UNLOCK;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
unlock_fs(fs, FR_OK);
|
unlock_fs(fs, FR_OK);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue