提交 bb3590a4 编写于 作者: O openharmony_ci 提交者: Gitee

!648 pagecache优化需求回合到LTS 3.0分支

Merge pull request !648 from LeonChan/pg3
......@@ -276,8 +276,8 @@ STATIC const CHAR *g_excTypeString[] = {
#ifdef LOSCFG_KERNEL_VM
STATIC VADDR_T OsGetTextRegionBase(LosVmMapRegion *region, LosProcessCB *runProcess)
{
struct file *curFilep = NULL;
struct file *lastFilep = NULL;
struct Vnode *curVnode = NULL;
struct Vnode *lastVnode = NULL;
LosVmMapRegion *curRegion = NULL;
LosVmMapRegion *lastRegion = NULL;
......@@ -296,9 +296,9 @@ STATIC VADDR_T OsGetTextRegionBase(LosVmMapRegion *region, LosProcessCB *runProc
if ((lastRegion == NULL) || !LOS_IsRegionFileValid(lastRegion)) {
goto DONE;
}
curFilep = curRegion->unTypeData.rf.file;
lastFilep = lastRegion->unTypeData.rf.file;
} while (!strcmp(curFilep->f_path, lastFilep->f_path));
curVnode = curRegion->unTypeData.rf.vnode;
lastVnode = lastRegion->unTypeData.rf.vnode;
} while (curVnode == lastVnode);
DONE:
#ifdef LOSCFG_KERNEL_DYNLOAD
......
......@@ -47,6 +47,7 @@
#include "user_copy.h"
#include "los_vm_filemap.h"
#include "los_hash.h"
#include "los_vm_common.h"
#include <time.h>
#include <errno.h>
#include <dirent.h>
......@@ -2180,6 +2181,207 @@ ERROUT:
return -fatfs_2_vfs(res);
}
ssize_t fatfs_readpage(struct Vnode *vnode, char *buff, off_t pos)
{
FATFS *fs = (FATFS *)(vnode->originMount->data);
DIR_FILE *dfp = (DIR_FILE *)(vnode->data);
FILINFO *finfo = &(dfp->fno);
FAT_ENTRY *ep = &(dfp->fat_entry);
DWORD clust;
DWORD sclust;
QWORD sect;
QWORD step;
QWORD n;
size_t position; /* byte offset */
BYTE *buf = (BYTE *)buff;
size_t buflen = PAGE_SIZE;
FRESULT result;
int ret;
ret = lock_fs(fs);
if (ret == FALSE) {
result = FR_TIMEOUT;
goto ERROR_OUT;
}
if (finfo->fsize <= pos) {
result = FR_OK;
goto ERROR_UNLOCK;
}
if (ep->clst == 0) {
ep->clst = finfo->sclst;
}
if (pos >= ep->pos) {
clust = ep->clst;
position = ep->pos;
} else {
clust = finfo->sclst;
position = 0;
}
/* Get to the current cluster */
n = pos / SS(fs) / fs->csize - position / SS(fs) / fs->csize;
while (n--) {
clust = get_fat(&(dfp->f_dir.obj), clust);
if ((clust == BAD_CLUSTER) || (clust == DISK_ERROR)) {
result = FR_DISK_ERR;
goto ERROR_UNLOCK;
}
}
/* Get to the currnet sector */
sect = clst2sect(fs, clust);
sect += (pos / SS(fs)) & (fs->csize - 1);
/* How many sectors do we need to read once */
if (fs->csize < buflen / SS(fs)) {
step = fs->csize;
} else {
step = buflen / SS(fs);
}
n = 0;
sclust = clust;
while (n < buflen / SS(fs)) {
if (disk_read(fs->pdrv, buf, sect, step) != RES_OK) {
result = FR_DISK_ERR;
goto ERROR_UNLOCK;
}
n += step;
if (n >= buflen / SS(fs)) {
break;
}
/* As cluster size is aligned, it must jump to next cluster when cluster size is less than pagesize */
clust = get_fat(&(dfp->f_dir.obj), clust);
if ((clust == BAD_CLUSTER) || (clust == DISK_ERROR)) {
result = FR_DISK_ERR;
goto ERROR_UNLOCK;
} else if (fatfs_is_last_cluster(fs, clust)) {
break; /* read end */
}
sect = clst2sect(fs, clust);
buf += step * SS(fs);
}
ep->clst = sclust;
ep->pos = pos;
unlock_fs(fs, FR_OK);
return (ssize_t)min(finfo->fsize - pos, n * SS(fs));
ERROR_UNLOCK:
unlock_fs(fs, result);
ERROR_OUT:
return -fatfs_2_vfs(result);
}
ssize_t fatfs_writepage(struct Vnode *vnode, char *buff, off_t pos, size_t buflen)
{
FATFS *fs = (FATFS *)(vnode->originMount->data);
DIR_FILE *dfp = (DIR_FILE *)(vnode->data);
FILINFO *finfo = &(dfp->fno);
FAT_ENTRY *ep = &(dfp->fat_entry);
DWORD clust;
DWORD sclst;
QWORD sect;
QWORD step;
QWORD n;
size_t position; /* byte offset */
BYTE *buf = (BYTE *)buff;
FRESULT result;
FIL fil;
int ret;
ret = lock_fs(fs);
if (ret == FALSE) {
result = FR_TIMEOUT;
goto ERROR_OUT;
}
if (finfo->fsize <= pos) {
result = FR_OK;
goto ERROR_UNLOCK;
}
if (ep->clst == 0) {
ep->clst = finfo->sclst;
}
if (pos >= ep->pos) {
clust = ep->clst;
position = ep->pos;
} else {
clust = finfo->sclst;
position = 0;
}
/* Get to the current cluster */
n = pos / SS(fs) / fs->csize - position / SS(fs) / fs->csize;
while (n--) {
clust = get_fat(&(dfp->f_dir.obj), clust);
if ((clust == BAD_CLUSTER) || (clust == DISK_ERROR)) {
result = FR_DISK_ERR;
goto ERROR_UNLOCK;
}
}
/* Get to the currnet sector */
sect = clst2sect(fs, clust);
sect += (pos / SS(fs)) & (fs->csize - 1);
/* How many sectors do we need to read once */
if (fs->csize < buflen / SS(fs)) {
step = fs->csize;
} else {
step = buflen / SS(fs);
}
n = 0;
sclst = clust;
while (n < buflen / SS(fs)) {
if (disk_write(fs->pdrv, buf, sect, step) != RES_OK) {
result = FR_DISK_ERR;
goto ERROR_UNLOCK;
}
n += step;
if (n >= buflen / SS(fs)) {
break;
}
/* As cluster size is aligned, it must jump to next cluster when cluster size is less than pagesize */
clust = get_fat(&(dfp->f_dir.obj), clust);
if ((clust == BAD_CLUSTER) || (clust == DISK_ERROR)) {
result = FR_DISK_ERR;
goto ERROR_UNLOCK;
} else if (fatfs_is_last_cluster(fs, clust)) {
break; /* read end */
}
sect = clst2sect(fs, clust);
buf += step * SS(fs);
}
ep->clst = sclst;
ep->pos = pos;
fil.obj.fs = fs;
if (update_filbuff(finfo, &fil, NULL) < 0) {
result = FR_DISK_ERR;
goto ERROR_UNLOCK;
}
unlock_fs(fs, FR_OK);
return (ssize_t)min(finfo->fsize - pos, n * SS(fs));
ERROR_UNLOCK:
unlock_fs(fs, result);
ERROR_OUT:
return -fatfs_2_vfs(result);
}
struct VnodeOps fatfs_vops = {
/* file ops */
.Getattr = fatfs_stat,
......@@ -2187,6 +2389,8 @@ struct VnodeOps fatfs_vops = {
.Lookup = fatfs_lookup,
.Rename = fatfs_rename,
.Create = fatfs_create,
.ReadPage = fatfs_readpage,
.WritePage = fatfs_writepage,
.Unlink = fatfs_unlink,
.Reclaim = fatfs_reclaim,
.Truncate = fatfs_truncate,
......
......@@ -41,81 +41,6 @@ extern "C" {
#endif /* __cplusplus */
#endif /* __cplusplus */
/* vfs/fs_file_mapping.c ****************************************************/
/****************************************************************************
* Name: init_file_mapping
*
* Description:
* Init the global management structure of path <-> page_mapping
*
****************************************************************************/
extern UINT32 init_file_mapping(void);
/****************************************************************************
* Name: add_mapping
*
* Description:
* Create a new path <-> page_mapping mapping and add to global list.
*
****************************************************************************/
extern void add_mapping(struct file *filep, const char *fullpath);
/****************************************************************************
* Name: find_mapping
*
* Description:
* Find the page_mapping for path in global list.
*
****************************************************************************/
extern struct page_mapping *find_mapping(const char *path);
/****************************************************************************
* Name: remove_mapping
*
* Description:
* Drop all the page-caches for the file, and then remove mapping between
* the file and pagecache.
* ex_filp NULL: do not exclude any file, just matching the fullpath;
* ex_filp not NULL: exclude it, which means, ex_filp can be open.
*
****************************************************************************/
extern int remove_mapping(const char *fullpath);
/****************************************************************************
* Name: rename_mapping
*
* Description:
* Rename the mapping from global path <-> page_mapping list.
*
****************************************************************************/
extern void rename_mapping(const char *src, const char *dst);
/****************************************************************************
* Name: dec_mapping
*
* Description:
* Decrease the refcnt of mapping.
*
****************************************************************************/
extern void dec_mapping_nolock(struct page_mapping *mapping);
/****************************************************************************
* Name: update_file_path
*
* Description:
* Update the path in file descriptors when do renaming.
*
****************************************************************************/
extern int update_file_path(const char *old_path, const char *new_path);
/**
* @ingroup fs
* @brief Initializes the vfs filesystem
......
......@@ -276,7 +276,7 @@ int VfsJffs2Close(struct file *filep)
return 0;
}
ssize_t VfsJffs2Read(struct file *filep, char *buffer, size_t bufLen)
ssize_t VfsJffs2ReadPage(struct Vnode *vnode, char *buffer, off_t off)
{
struct jffs2_inode *node = NULL;
struct jffs2_inode_info *f = NULL;
......@@ -285,6 +285,32 @@ ssize_t VfsJffs2Read(struct file *filep, char *buffer, size_t bufLen)
LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
node = (struct jffs2_inode *)vnode->data;
f = JFFS2_INODE_INFO(node);
c = JFFS2_SB_INFO(node->i_sb);
off_t pos = min(node->i_size, off);
ssize_t len = min(PAGE_SIZE, (node->i_size - pos));
ret = jffs2_read_inode_range(c, f, (unsigned char *)buffer, off, len);
if (ret) {
LOS_MuxUnlock(&g_jffs2FsLock);
return ret;
}
node->i_atime = Jffs2CurSec();
LOS_MuxUnlock(&g_jffs2FsLock);
return len;
}
ssize_t VfsJffs2Read(struct file *filep, char *buffer, size_t bufLen)
{
struct jffs2_inode *node = NULL;
struct jffs2_inode_info *f = NULL;
struct jffs2_sb_info *c = NULL;
int ret;
LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
node = (struct jffs2_inode *)filep->f_vnode->data;
f = JFFS2_INODE_INFO(node);
c = JFFS2_SB_INFO(node->i_sb);
......@@ -293,7 +319,6 @@ ssize_t VfsJffs2Read(struct file *filep, char *buffer, size_t bufLen)
off_t len = min(bufLen, (node->i_size - pos));
ret = jffs2_read_inode_range(c, f, (unsigned char *)buffer, filep->f_pos, len);
if (ret) {
PRINTK("VfsJffs2Read(): read_inode_range failed %d\n", ret);
LOS_MuxUnlock(&g_jffs2FsLock);
return ret;
}
......@@ -305,6 +330,59 @@ ssize_t VfsJffs2Read(struct file *filep, char *buffer, size_t bufLen)
return len;
}
ssize_t VfsJffs2WritePage(struct Vnode *vnode, char *buffer, off_t pos, size_t buflen)
{
struct jffs2_inode *node = NULL;
struct jffs2_inode_info *f = NULL;
struct jffs2_sb_info *c = NULL;
struct jffs2_raw_inode ri = {0};
struct IATTR attr = {0};
int ret;
uint32_t writtenLen;
LOS_MuxLock(&g_jffs2FsLock, (uint32_t)JFFS2_WAITING_FOREVER);
node = (struct jffs2_inode *)vnode->data;
f = JFFS2_INODE_INFO(node);
c = JFFS2_SB_INFO(node->i_sb);
if (pos < 0) {
LOS_MuxUnlock(&g_jffs2FsLock);
return -EINVAL;
}
ri.ino = cpu_to_je32(f->inocache->ino);
ri.mode = cpu_to_jemode(node->i_mode);
ri.uid = cpu_to_je16(node->i_uid);
ri.gid = cpu_to_je16(node->i_gid);
ri.atime = ri.ctime = ri.mtime = cpu_to_je32(Jffs2CurSec());
if (pos > node->i_size) {
int err;
attr.attr_chg_valid = CHG_SIZE;
attr.attr_chg_size = pos;
err = jffs2_setattr(node, &attr);
if (err) {
LOS_MuxUnlock(&g_jffs2FsLock);
return err;
}
}
ri.isize = cpu_to_je32(node->i_size);
ret = jffs2_write_inode_range(c, f, &ri, (unsigned char *)buffer, pos, buflen, &writtenLen);
if (ret) {
node->i_mtime = node->i_ctime = je32_to_cpu(ri.mtime);
LOS_MuxUnlock(&g_jffs2FsLock);
return ret;
}
node->i_mtime = node->i_ctime = je32_to_cpu(ri.mtime);
LOS_MuxUnlock(&g_jffs2FsLock);
return (ssize_t)writtenLen;
}
ssize_t VfsJffs2Write(struct file *filep, const char *buffer, size_t bufLen)
{
struct jffs2_inode *node = NULL;
......@@ -878,6 +956,8 @@ const struct MountOps jffs_operations = {
struct VnodeOps g_jffs2Vops = {
.Lookup = VfsJffs2Lookup,
.Create = VfsJffs2Create,
.ReadPage = VfsJffs2ReadPage,
.WritePage = VfsJffs2WritePage,
.Rename = VfsJffs2Rename,
.Mkdir = VfsJffs2Mkdir,
.Getattr = VfsJffs2Stat,
......
......@@ -71,9 +71,9 @@ static int VnodeListProcess(struct SeqBuf *buf, LIST_HEAD* list)
struct Vnode *nextItem = NULL;
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, list, struct Vnode, actFreeEntry) {
LosBufPrintf(buf, "%-10p %-10p %-10p %10p 0x%08x %-3d %-4s %-3d %-3d %o\n",
LosBufPrintf(buf, "%-10p %-10p %-10p %10p 0x%08x %-3d %-4s %-3d %-3d %-8o\t%s\n",
item, item->parent, item->data, item->vop, item->hash, item->useCount,
VnodeTypeToStr(item->type), item->gid, item->uid, item->mode);
VnodeTypeToStr(item->type), item->gid, item->uid, item->mode, item->filePath);
count++;
}
......@@ -104,7 +104,7 @@ static int PageCacheEntryProcess(struct SeqBuf *buf, struct page_mapping *mappin
int total = 0;
LosFilePage *fpage = NULL;
if (mapping == NULL) {
if (mapping->nrpages == 0) {
LosBufPrintf(buf, "null]\n");
return total;
}
......@@ -119,18 +119,18 @@ static int PageCacheEntryProcess(struct SeqBuf *buf, struct page_mapping *mappin
static int PageCacheMapProcess(struct SeqBuf *buf)
{
struct file_map *mapList = GetFileMappingList();
char *name = NULL;
struct file_map *curMap = NULL;
LIST_HEAD *vnodeList = GetVnodeActiveList();
struct page_mapping *mapping = NULL;
struct Vnode *vnode = NULL;
int total = 0;
(VOID)LOS_MuxLock(&mapList->lock, LOS_WAIT_FOREVER);
LOS_DL_LIST_FOR_EACH_ENTRY(curMap, &mapList->head, struct file_map, head) {
name = curMap->rename ? curMap->rename: curMap->owner;
LosBufPrintf(buf, "%s:[", name);
total += PageCacheEntryProcess(buf, &curMap->mapping);
VnodeHold();
LOS_DL_LIST_FOR_EACH_ENTRY(vnode, vnodeList, struct Vnode, actFreeEntry) {
mapping = &vnode->mapping;
LosBufPrintf(buf, "%p, %s:[", vnode, vnode->filePath);
total += PageCacheEntryProcess(buf, mapping);
}
(VOID)LOS_MuxUnlock(&mapList->lock);
VnodeDrop();
return total;
}
......
......@@ -40,7 +40,6 @@ kernel_module(module_name) {
"operation/vfs_fallocate.c",
"operation/vfs_fallocate64.c",
"operation/vfs_fcntl.c",
"operation/vfs_file_mapping.c",
"operation/vfs_force_umount.c",
"operation/vfs_init.c",
"operation/vfs_other.c",
......
......@@ -125,12 +125,16 @@ struct Vnode {
LIST_ENTRY actFreeEntry; /* vnode active/free list entry */
struct Mount *originMount; /* fs info about this vnode */
struct Mount *newMount; /* fs info about who mount on this vnode */
char *filePath; /* file path of the vnode */
struct page_mapping mapping; /* page mapping of the vnode */
};
struct VnodeOps {
int (*Create)(struct Vnode *parent, const char *name, int mode, struct Vnode **vnode);
int (*Lookup)(struct Vnode *parent, const char *name, int len, struct Vnode **vnode);
int (*Open)(struct Vnode *vnode, int fd, int mode, int flags);
ssize_t (*ReadPage)(struct Vnode *vnode, char *buffer, off_t pos);
ssize_t (*WritePage)(struct Vnode *vnode, char *buffer, off_t pos, size_t buflen);
int (*Close)(struct Vnode *vnode);
int (*Reclaim)(struct Vnode *vnode);
int (*Unlink)(struct Vnode *parent, struct Vnode *vnode, const char *fileName);
......
/*
* Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
* Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "fs/file.h"
#include "fs/file.h"
#include "fs/fs_operation.h"
#include "unistd.h"
#include "los_mux.h"
#include "los_list.h"
#include "los_atomic.h"
#include "los_vm_filemap.h"
#ifdef LOSCFG_KERNEL_VM
static struct file_map g_file_mapping = {0};
uint init_file_mapping()
{
uint ret;
LOS_ListInit(&g_file_mapping.head);
ret = LOS_MuxInit(&g_file_mapping.lock, NULL);
if (ret != LOS_OK) {
PRINT_ERR("Create mutex for file map of page cache failed, (ret=%u)\n", ret);
}
return ret;
}
static void clear_file_mapping(const struct page_mapping *mapping)
{
unsigned int i = 3; /* file start fd */
struct file *filp = NULL;
while (i < CONFIG_NFILE_DESCRIPTORS) {
filp = &tg_filelist.fl_files[i];
if (filp->f_mapping == mapping) {
filp->f_mapping = NULL;
}
i++;
}
}
static struct page_mapping *find_mapping_nolock(const char *fullpath)
{
char *map_name = NULL;
struct file_map *fmap = NULL;
int name_len = strlen(fullpath);
LOS_DL_LIST_FOR_EACH_ENTRY(fmap, &g_file_mapping.head, struct file_map, head) {
map_name = fmap->rename ? fmap->rename: fmap->owner;
if ((name_len == fmap->name_len) && !strcmp(map_name, fullpath)) {
return &fmap->mapping;
}
}
return NULL;
}
void add_mapping(struct file *filep, const char *fullpath)
{
int path_len;
status_t retval;
struct file_map *fmap = NULL;
struct page_mapping *mapping = NULL;
if (filep == NULL || fullpath == NULL) {
return;
}
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
mapping = find_mapping_nolock(fullpath);
if (mapping) {
LOS_AtomicInc(&mapping->ref);
filep->f_mapping = mapping;
mapping->host = filep;
goto out;
}
path_len = strlen(fullpath);
fmap = (struct file_map *)zalloc(sizeof(struct file_map) + path_len + 1);
if (!fmap) {
PRINT_WARN("%s %d, Mem alloc failed.\n", __FUNCTION__, __LINE__);
goto out;
}
LOS_AtomicSet(&fmap->mapping.ref, 1);
fmap->name_len = path_len;
(void)strcpy_s(fmap->owner, path_len + 1, fullpath);
LOS_ListInit(&fmap->mapping.page_list);
LOS_SpinInit(&fmap->mapping.list_lock);
retval = LOS_MuxInit(&fmap->mapping.mux_lock, NULL);
if (retval != LOS_OK) {
PRINT_ERR("%s %d, Create mutex for mapping.mux_lock failed, status: %d\n", __FUNCTION__, __LINE__, retval);
goto out;
}
LOS_ListTailInsert(&g_file_mapping.head, &fmap->head);
filep->f_mapping = &fmap->mapping;
filep->f_mapping->host = filep;
out:
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);
}
int remove_mapping_nolock(struct page_mapping *mapping)
{
struct file_map *fmap = NULL;
if (mapping == NULL) {
set_errno(EINVAL);
return EINVAL;
}
(VOID)LOS_MuxDestroy(&mapping->mux_lock);
clear_file_mapping(mapping);
OsFileCacheRemove(mapping);
fmap = LOS_DL_LIST_ENTRY(mapping, struct file_map, mapping);
LOS_ListDelete(&fmap->head);
if (fmap->rename) {
LOS_MemFree(m_aucSysMem0, fmap->rename);
}
LOS_MemFree(m_aucSysMem0, fmap);
return OK;
}
void dec_mapping_nolock(struct page_mapping *mapping)
{
if (mapping == NULL) {
return;
}
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
if (LOS_AtomicRead(&mapping->ref) > 0) {
LOS_AtomicDec(&mapping->ref);
}
if (LOS_AtomicRead(&mapping->ref) <= 0) {
remove_mapping_nolock(mapping);
} else {
OsFileCacheFlush(mapping);
}
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);
}
int remove_mapping(const char *fullpath)
{
int ret;
struct filelist *f_list = NULL;
struct page_mapping *mapping = NULL;
f_list = &tg_filelist;
ret = sem_wait(&f_list->fl_sem);
if (ret < 0) {
PRINTK("sem_wait error, ret=%d\n", ret);
return VFS_ERROR;
}
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
mapping = find_mapping_nolock(fullpath);
if (mapping) {
ret = remove_mapping_nolock(mapping);
}
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);
(void)sem_post(&f_list->fl_sem);
return OK;
}
void rename_mapping(const char *src_path, const char *dst_path)
{
int ret;
char *tmp = NULL;
int path_len;
struct file_map *fmap = NULL;
struct page_mapping *mapping = NULL;
if (src_path == NULL || dst_path == NULL) {
return;
}
path_len = strlen(dst_path);
/* protect the whole list in case of this node been deleted just after we found it */
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
mapping = find_mapping_nolock(src_path);
if (!mapping) {
goto out;
}
fmap = LOS_DL_LIST_ENTRY(mapping, struct file_map, mapping);
tmp = LOS_MemAlloc(m_aucSysMem0, path_len + 1);
if (!tmp) {
PRINT_ERR("%s-%d: Mem alloc failed, path length(%d)\n", __FUNCTION__, __LINE__, path_len);
goto out;
}
ret = strncpy_s(tmp, path_len, dst_path, strlen(dst_path));
if (ret != 0) {
(VOID)LOS_MemFree(m_aucSysMem0, tmp);
goto out;
}
tmp[path_len] = '\0';
fmap->rename = tmp;
out:
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);
}
int update_file_path(const char *old_path, const char *new_path)
{
struct filelist *f_list = NULL;
struct file *filp = NULL;
int ret;
f_list = &tg_filelist;
ret = sem_wait(&f_list->fl_sem);
if (ret < 0) {
PRINTK("sem_wait error, ret=%d\n", ret);
return VFS_ERROR;
}
(VOID)LOS_MuxLock(&g_file_mapping.lock, LOS_WAIT_FOREVER);
for (int i = 3; i < CONFIG_NFILE_DESCRIPTORS; i++) {
if (!get_bit(i)) {
continue;
}
filp = &tg_filelist.fl_files[i];
if (filp->f_path == NULL || strcmp(filp->f_path, old_path)) {
continue;
}
int len = strlen(new_path) + 1;
char *tmp_path = LOS_MemAlloc(m_aucSysMem0, len);
if (tmp_path == NULL) {
PRINT_ERR("%s-%d: Mem alloc failed, path length(%d)\n", __FUNCTION__, __LINE__, len);
ret = VFS_ERROR;
goto out;
}
ret = strncpy_s(tmp_path, strlen(new_path) + 1, new_path, len);
if (ret != 0) {
(VOID)LOS_MemFree(m_aucSysMem0, tmp_path);
PRINT_ERR("%s-%d: strcpy failed.\n", __FUNCTION__, __LINE__);
ret = VFS_ERROR;
goto out;
}
free(filp->f_path);
filp->f_path = tmp_path;
}
ret = LOS_OK;
out:
(VOID)LOS_MuxUnlock(&g_file_mapping.lock);
(void)sem_post(&f_list->fl_sem);
return ret;
}
#ifdef LOSCFG_DEBUG_VERSION
struct file_map* GetFileMappingList(void)
{
return &g_file_mapping;
}
#endif
#endif
......@@ -79,14 +79,7 @@ void los_vfs_init(void)
PRINT_ERR("los_vfs_init VnodeDevInit failed error %d\n", retval);
return;
}
#ifdef LOSCFG_KERNEL_VM
retval = init_file_mapping();
if (retval != LOS_OK) {
PRINT_ERR("Page cache file map init failed\n");
return;
}
#endif
g_vfs_init = true;
}
......
......@@ -65,6 +65,7 @@ int VnodesInit(void)
}
g_rootVnode->mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR;
g_rootVnode->type = VNODE_TYPE_DIR;
g_rootVnode->filePath = "/";
return LOS_OK;
}
......@@ -155,6 +156,11 @@ int VnodeAlloc(struct VnodeOps *vop, struct Vnode **newVnode)
LOS_ListTailInsert(&g_vnodeActiveList, &(vnode->actFreeEntry));
vnode->vop = vop;
}
LOS_ListInit(&vnode->mapping.page_list);
LOS_SpinInit(&vnode->mapping.list_lock);
(VOID)LOS_MuxInit(&vnode->mapping.mux_lock, NULL);
vnode->mapping.host = vnode;
VnodeDrop();
*newVnode = vnode;
......@@ -182,6 +188,9 @@ int VnodeFree(struct Vnode *vnode)
vnode->vop->Reclaim(vnode);
}
if (vnode->filePath) {
free(vnode->filePath);
}
if (vnode->vop == &g_devfsOps) {
/* for dev vnode, just free it */
free(vnode->data);
......@@ -363,6 +372,8 @@ STEP_FINISH:
int VnodeLookupAt(const char *path, struct Vnode **result, uint32_t flags, struct Vnode *orgVnode)
{
int ret;
int vnodePathLen;
char *vnodePath = NULL;
struct Vnode *startVnode = NULL;
char *normalizedPath = NULL;
......@@ -391,7 +402,12 @@ int VnodeLookupAt(const char *path, struct Vnode **result, uint32_t flags, struc
if (currentDir == NULL || *currentDir == '\0') {
// return target or parent vnode as result
*result = currentVnode;
goto OUT_FREE_PATH;
if (currentVnode->filePath == NULL) {
currentVnode->filePath = normalizedPath;
} else {
free(normalizedPath);
}
return ret;
} else if (VfsVnodePermissionCheck(currentVnode, EXEC_OP)) {
ret = -EACCES;
goto OUT_FREE_PATH;
......@@ -401,13 +417,28 @@ int VnodeLookupAt(const char *path, struct Vnode **result, uint32_t flags, struc
// no such file, lookup failed
goto OUT_FREE_PATH;
}
if (currentVnode->filePath == NULL) {
vnodePathLen = currentDir - normalizedPath;
vnodePath = malloc(vnodePathLen + 1);
if (vnodePath == NULL) {
ret = -ENOMEM;
goto OUT_FREE_PATH;
}
ret = strncpy_s(vnodePath, vnodePathLen + 1, normalizedPath, vnodePathLen);
if (ret != EOK) {
ret = -ENAMETOOLONG;
free(vnodePath);
goto OUT_FREE_PATH;
}
currentVnode->filePath = vnodePath;
currentVnode->filePath[vnodePathLen] = 0;
}
}
OUT_FREE_PATH:
if (normalizedPath) {
free(normalizedPath);
}
return ret;
}
......@@ -534,6 +565,9 @@ int VnodeCreate(struct Vnode *parent, const char *name, int mode, struct Vnode *
newVnode->uid = parent->uid;
newVnode->gid = parent->gid;
newVnode->mode = mode;
/* The 'name' here is not full path, but for device we don't depend on this path, it's just a name for DFx.
When we have devfs, we can get a fullpath. */
newVnode->filePath = strdup(name);
*vnode = newVnode;
return 0;
......
......@@ -121,7 +121,7 @@ typedef struct ProcessCB {
TimerIdMap timerIdMap;
#endif
#ifdef LOSCFG_DRIVERS_TZDRIVER
struct file *execFile; /**< Exec bin of the process */
struct Vnode *execVnode; /**< Exec bin of the process */
#endif
mode_t umask;
#ifdef LOSCFG_KERNEL_CPUP
......
......@@ -44,6 +44,8 @@
#include "los_vm_zone.h"
#include "los_vm_common.h"
struct Vnode;
#ifdef __cplusplus
#if __cplusplus
extern "C" {
......@@ -91,8 +93,8 @@ struct VmMapRegion {
UINT8 regionType; /**< vm region type: ANON, FILE, DEV */
union {
struct VmRegionFile {
unsigned int fileMagic;
struct file *file;
int f_oflags;
struct Vnode *vnode;
const LosVmFileOps *vmFOps;
} rf;
struct VmRegionAnon {
......
......@@ -38,6 +38,7 @@
#include "los_mmu_descriptor_v6.h"
#ifdef LOSCFG_FS_VFS
#include "fs/file.h"
#include "vnode.h"
#endif
#include "los_printf.h"
#include "los_vm_page.h"
......@@ -55,13 +56,13 @@
const CHAR *OsGetRegionNameOrFilePath(LosVmMapRegion *region)
{
struct file *filep = NULL;
struct Vnode *vnode = NULL;
if (region == NULL) {
return "";
#ifdef LOSCFG_FS_VFS
} else if (LOS_IsRegionFileValid(region)) {
filep = region->unTypeData.rf.file;
return filep->f_path;
vnode = region->unTypeData.rf.vnode;
return vnode->filePath;
#endif
} else if (region->regionFlags & VM_MAP_REGION_FLAG_HEAP) {
return "HEAP";
......
......@@ -45,6 +45,10 @@
#include "los_process_pri.h"
#include "arm.h"
#ifdef LOSCFG_FS_VFS
#include "vnode.h"
#endif
#ifdef LOSCFG_KERNEL_VM
......@@ -106,11 +110,11 @@ STATIC STATUS_T OsDoReadFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
return LOS_OK;
}
if (region->unTypeData.rf.vmFOps == NULL || region->unTypeData.rf.vmFOps->fault == NULL) {
VM_ERR("region args invalid, file path: %s", region->unTypeData.rf.file->f_path);
VM_ERR("region args invalid, file path: %s", region->unTypeData.rf.vnode->filePath);
return LOS_ERRNO_VM_INVALID_ARGS;
}
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.vnode->mapping.mux_lock);
ret = region->unTypeData.rf.vmFOps->fault(region, vmPgFault);
if (ret == LOS_OK) {
paddr = LOS_PaddrQuery(vmPgFault->pageKVaddr);
......@@ -124,14 +128,14 @@ STATIC STATUS_T OsDoReadFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
if (ret < 0) {
VM_ERR("LOS_ArchMmuMap failed");
OsDelMapInfo(region, vmPgFault, false);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
return LOS_ERRNO_VM_NO_MEMORY;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
return LOS_OK;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
return LOS_ERRNO_VM_NO_MEMORY;
}
......@@ -145,8 +149,8 @@ STATIC LosVmPage *OsCowUnmapOrg(LosArchMmu *archMmu, LosVmMapRegion *region, Los
LosFilePage *fpage = NULL;
VADDR_T vaddr = (VADDR_T)vmf->vaddr;
LOS_SpinLockSave(&region->unTypeData.rf.file->f_mapping->list_lock, &intSave);
fpage = OsFindGetEntry(region->unTypeData.rf.file->f_mapping, vmf->pgoff);
LOS_SpinLockSave(&region->unTypeData.rf.vnode->mapping.list_lock, &intSave);
fpage = OsFindGetEntry(&region->unTypeData.rf.vnode->mapping, vmf->pgoff);
if (fpage != NULL) {
oldPage = fpage->vmPage;
OsSetPageLocked(oldPage);
......@@ -159,7 +163,7 @@ STATIC LosVmPage *OsCowUnmapOrg(LosArchMmu *archMmu, LosVmMapRegion *region, Los
} else {
LOS_ArchMmuUnmap(archMmu, vaddr, 1);
}
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
LOS_SpinUnlockRestore(&region->unTypeData.rf.vnode->mapping.list_lock, intSave);
return oldPage;
}
......@@ -197,11 +201,11 @@ status_t OsDoCowFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
newPaddr = VM_PAGE_TO_PHYS(newPage);
kvaddr = OsVmPageToVaddr(newPage);
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.vnode->mapping.mux_lock);
ret = region->unTypeData.rf.vmFOps->fault(region, vmPgFault);
if (ret != LOS_OK) {
VM_ERR("call region->vm_ops->fault fail");
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
goto ERR_OUT;
}
......@@ -227,10 +231,10 @@ status_t OsDoCowFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
if (ret < 0) {
VM_ERR("LOS_ArchMmuMap failed");
ret = LOS_ERRNO_VM_NO_MEMORY;
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
goto ERR_OUT;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
if (oldPage != NULL) {
OsCleanPageLocked(oldPage);
......@@ -273,17 +277,17 @@ status_t OsDoSharedFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
return LOS_ERRNO_VM_NO_MEMORY;
}
LOS_SpinLockSave(&region->unTypeData.rf.file->f_mapping->list_lock, &intSave);
fpage = OsFindGetEntry(region->unTypeData.rf.file->f_mapping, vmPgFault->pgoff);
LOS_SpinLockSave(&region->unTypeData.rf.vnode->mapping.list_lock, &intSave);
fpage = OsFindGetEntry(&region->unTypeData.rf.vnode->mapping, vmPgFault->pgoff);
if (fpage) {
OsMarkPageDirty(fpage, region, 0, 0);
}
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
LOS_SpinUnlockRestore(&region->unTypeData.rf.vnode->mapping.list_lock, intSave);
return LOS_OK;
}
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxAcquire(&region->unTypeData.rf.vnode->mapping.mux_lock);
ret = region->unTypeData.rf.vmFOps->fault(region, vmPgFault);
if (ret == LOS_OK) {
paddr = LOS_PaddrQuery(vmPgFault->pageKVaddr);
......@@ -297,14 +301,14 @@ status_t OsDoSharedFault(LosVmMapRegion *region, LosVmPgFault *vmPgFault)
if (ret < 0) {
VM_ERR("LOS_ArchMmuMap failed. ret=%d", ret);
OsDelMapInfo(region, vmPgFault, TRUE);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
return LOS_ERRNO_VM_NO_MEMORY;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
return LOS_OK;
}
(VOID)LOS_MuxRelease(&region->unTypeData.rf.file->f_mapping->mux_lock);
(VOID)LOS_MuxRelease(&region->unTypeData.rf.vnode->mapping.mux_lock);
return ret;
}
......@@ -382,7 +386,7 @@ STATUS_T OsVmPageFaultHandler(VADDR_T vaddr, UINT32 flags, ExcContext *frame)
vaddr = ROUNDDOWN(vaddr, PAGE_SIZE);
#ifdef LOSCFG_FS_VFS
if (LOS_IsRegionFileValid(region)) {
if (region->unTypeData.rf.file->f_mapping == NULL) {
if (region->unTypeData.rf.vnode == NULL) {
goto CHECK_FAILED;
}
vmPgFault.vaddr = vaddr;
......
......@@ -172,17 +172,17 @@ VOID OsVmmFileRemove(LosVmMapRegion *region, LosArchMmu *archMmu, VM_OFFSET_T pg
UINT32 intSave;
vaddr_t vaddr;
paddr_t paddr = 0;
struct file *file = NULL;
struct Vnode *vnode = NULL;
struct page_mapping *mapping = NULL;
LosFilePage *fpage = NULL;
LosFilePage *tmpPage = NULL;
LosVmPage *mapPage = NULL;
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.file->f_mapping == NULL)) {
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.vnode == NULL)) {
return;
}
file = region->unTypeData.rf.file;
mapping = file->f_mapping;
vnode = region->unTypeData.rf.vnode;
mapping = &vnode->mapping;
vaddr = region->range.base + ((UINT32)(pgoff - region->pgOff) << PAGE_SHIFT);
status_t status = LOS_ArchMmuQuery(archMmu, vaddr, &paddr, NULL);
......@@ -232,15 +232,15 @@ VOID OsMarkPageDirty(LosFilePage *fpage, LosVmMapRegion *region, INT32 off, INT3
}
}
STATIC UINT32 GetDirtySize(LosFilePage *fpage, struct file *file)
STATIC UINT32 GetDirtySize(LosFilePage *fpage, struct Vnode *vnode)
{
UINT32 fileSize;
UINT32 dirtyBegin;
UINT32 dirtyEnd;
struct stat buf_stat;
if (stat(file->f_path, &buf_stat) != OK) {
VM_ERR("FlushDirtyPage get file size failed. (filepath=%s)", file->f_path);
if (stat(vnode->filePath, &buf_stat) != OK) {
VM_ERR("FlushDirtyPage get file size failed. (filePath=%s)", vnode->filePath);
return 0;
}
......@@ -264,31 +264,29 @@ STATIC INT32 OsFlushDirtyPage(LosFilePage *fpage)
UINT32 ret;
size_t len;
char *buff = NULL;
VM_OFFSET_T oldPos;
struct file *file = fpage->mapping->host;
if ((file == NULL) || (file->f_vnode == NULL)) {
VM_ERR("page cache file error");
struct Vnode *vnode = fpage->mapping->host;
if (vnode == NULL) {
VM_ERR("page cache vnode error");
return LOS_NOK;
}
oldPos = file_seek(file, 0, SEEK_CUR);
buff = (char *)OsVmPageToVaddr(fpage->vmPage);
file_seek(file, (((UINT32)fpage->pgoff << PAGE_SHIFT) + fpage->dirtyOff), SEEK_SET);
len = fpage->dirtyEnd - fpage->dirtyOff;
len = (len == 0) ? GetDirtySize(fpage, file) : len;
len = (len == 0) ? GetDirtySize(fpage, vnode) : len;
if (len == 0) {
OsCleanPageDirty(fpage->vmPage);
(VOID)file_seek(file, oldPos, SEEK_SET);
return LOS_OK;
}
ret = file_write(file, (VOID *)buff, len);
buff = (char *)OsVmPageToVaddr(fpage->vmPage);
/* actually, we did not update the fpage->dirtyOff */
ret = vnode->vop->WritePage(vnode, (VOID *)buff, fpage->pgoff, len);
if (ret <= 0) {
VM_ERR("WritePage error ret %d", ret);
} else {
OsCleanPageDirty(fpage->vmPage);
}
ret = (ret <= 0) ? LOS_NOK : LOS_OK;
OsCleanPageDirty(fpage->vmPage);
(VOID)file_seek(file, oldPos, SEEK_SET);
return ret;
}
......@@ -336,15 +334,17 @@ VOID OsDelMapInfo(LosVmMapRegion *region, LosVmPgFault *vmf, BOOL cleanDirty)
UINT32 intSave;
LosMapInfo *info = NULL;
LosFilePage *fpage = NULL;
struct page_mapping *mapping = NULL;
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.file->f_mapping == NULL) || (vmf == NULL)) {
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.vnode == NULL) || (vmf == NULL)) {
return;
}
LOS_SpinLockSave(&region->unTypeData.rf.file->f_mapping->list_lock, &intSave);
fpage = OsFindGetEntry(region->unTypeData.rf.file->f_mapping, vmf->pgoff);
mapping = &region->unTypeData.rf.vnode->mapping;
LOS_SpinLockSave(&mapping->list_lock, &intSave);
fpage = OsFindGetEntry(mapping, vmf->pgoff);
if (fpage == NULL) {
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
return;
}
......@@ -356,31 +356,30 @@ VOID OsDelMapInfo(LosVmMapRegion *region, LosVmPgFault *vmf, BOOL cleanDirty)
fpage->n_maps--;
LOS_ListDelete(&info->node);
LOS_AtomicDec(&fpage->vmPage->refCounts);
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
LOS_MemFree(m_aucSysMem0, info);
return;
}
LOS_SpinUnlockRestore(&region->unTypeData.rf.file->f_mapping->list_lock, intSave);
LOS_SpinUnlockRestore(&mapping->list_lock, intSave);
}
INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
{
INT32 ret;
VM_OFFSET_T oldPos;
VOID *kvaddr = NULL;
UINT32 intSave;
bool newCache = false;
struct file *file = NULL;
struct Vnode *vnode = NULL;
struct page_mapping *mapping = NULL;
LosFilePage *fpage = NULL;
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.file->f_mapping == NULL) || (vmf == NULL)) {
if (!LOS_IsRegionFileValid(region) || (region->unTypeData.rf.vnode == NULL) || (vmf == NULL)) {
VM_ERR("Input param is NULL");
return LOS_NOK;
}
file = region->unTypeData.rf.file;
mapping = file->f_mapping;
vnode = region->unTypeData.rf.vnode;
mapping = &vnode->mapping;
/* get or create a new cache node */
LOS_SpinLockSave(&mapping->list_lock, &intSave);
......@@ -404,10 +403,7 @@ INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
/* read file to new page cache */
if (newCache) {
oldPos = file_seek(file, 0, SEEK_CUR);
file_seek(file, fpage->pgoff << PAGE_SHIFT, SEEK_SET);
ret = file_read(file, kvaddr, PAGE_SIZE);
file_seek(file, oldPos, SEEK_SET);
ret = vnode->vop->ReadPage(vnode, kvaddr, fpage->pgoff << PAGE_SHIFT);
if (ret == 0) {
VM_ERR("Failed to read from file!");
OsReleaseFpage(mapping, fpage);
......@@ -505,8 +501,9 @@ LosVmFileOps g_commVmOps = {
INT32 OsVfsFileMmap(struct file *filep, LosVmMapRegion *region)
{
region->unTypeData.rf.vmFOps = &g_commVmOps;
region->unTypeData.rf.file = filep;
region->unTypeData.rf.fileMagic = filep->f_magicnum;
region->unTypeData.rf.vnode = filep->f_vnode;
region->unTypeData.rf.f_oflags = filep->f_oflags;
return ENOERR;
}
......@@ -516,11 +513,11 @@ STATUS_T OsNamedMMap(struct file *filep, LosVmMapRegion *region)
if (filep == NULL) {
return LOS_ERRNO_VM_MAP_FAILED;
}
file_hold(filep);
vnode = filep->f_vnode;
if (vnode == NULL) {
return LOS_ERRNO_VM_MAP_FAILED;
}
VnodeHold();
vnode->useCount++;
VnodeDrop();
if (filep->ops != NULL && filep->ops->mmap != NULL) {
if (vnode->type == VNODE_TYPE_CHR || vnode->type == VNODE_TYPE_BLK) {
LOS_SetRegionTypeDev(region);
......@@ -529,12 +526,15 @@ STATUS_T OsNamedMMap(struct file *filep, LosVmMapRegion *region)
}
int ret = filep->ops->mmap(filep, region);
if (ret != LOS_OK) {
file_release(filep);
return LOS_ERRNO_VM_MAP_FAILED;
}
} else {
VM_ERR("mmap file type unknown");
file_release(filep);
return LOS_ERRNO_VM_MAP_FAILED;
}
file_release(filep);
return LOS_OK;
}
......@@ -600,40 +600,7 @@ LosFilePage *OsPageCacheAlloc(struct page_mapping *mapping, VM_OFFSET_T pgoff)
return fpage;
}
#ifdef LOSCFG_FS_VFS
VOID OsVmmFileRegionFree(struct file *filep, LosProcessCB *processCB)
{
int ret;
LosVmSpace *space = NULL;
LosVmMapRegion *region = NULL;
LosRbNode *pstRbNode = NULL;
LosRbNode *pstRbNodeTmp = NULL;
if (processCB == NULL) {
processCB = OsCurrProcessGet();
}
space = processCB->vmSpace;
if (space != NULL) {
(VOID)LOS_MuxAcquire(&space->regionMux);
/* free the regions associated with filep */
RB_SCAN_SAFE(&space->regionRbTree, pstRbNode, pstRbNodeTmp)
region = (LosVmMapRegion *)pstRbNode;
if (LOS_IsRegionFileValid(region)) {
if (region->unTypeData.rf.file != filep) {
continue;
}
ret = LOS_RegionFree(space, region);
if (ret != LOS_OK) {
VM_ERR("free region error, space %p, region %p", space, region);
}
}
RB_SCAN_SAFE_END(&space->regionRbTree, pstRbNode, pstRbNodeTmp)
(VOID)LOS_MuxRelease(&space->regionMux);
}
}
#endif
#else
#ifndef LOSCFG_FS_VFS
INT32 OsVfsFileMmap(struct file *filep, LosVmMapRegion *region)
{
UNUSED(filep);
......@@ -642,3 +609,4 @@ INT32 OsVfsFileMmap(struct file *filep, LosVmMapRegion *region)
}
#endif
#endif
......@@ -42,6 +42,7 @@
#include "los_process_pri.h"
#ifdef LOSCFG_FS_VFS
#include "fs/file.h"
#include "vnode.h"
#endif
#include "los_task.h"
#include "los_memory_pri.h"
......@@ -308,12 +309,12 @@ STATUS_T LOS_VmSpaceClone(LosVmSpace *oldVmSpace, LosVmSpace *newVmSpace)
#ifdef LOSCFG_FS_VFS
if (LOS_IsRegionFileValid(oldRegion)) {
LosFilePage *fpage = NULL;
LOS_SpinLockSave(&oldRegion->unTypeData.rf.file->f_mapping->list_lock, &intSave);
fpage = OsFindGetEntry(oldRegion->unTypeData.rf.file->f_mapping, newRegion->pgOff + i);
LOS_SpinLockSave(&oldRegion->unTypeData.rf.vnode->mapping.list_lock, &intSave);
fpage = OsFindGetEntry(&oldRegion->unTypeData.rf.vnode->mapping, newRegion->pgOff + i);
if ((fpage != NULL) && (fpage->vmPage == page)) { /* cow page no need map */
OsAddMapInfo(fpage, &newVmSpace->archMmu, vaddr);
}
LOS_SpinUnlockRestore(&oldRegion->unTypeData.rf.file->f_mapping->list_lock, intSave);
LOS_SpinUnlockRestore(&oldRegion->unTypeData.rf.vnode->mapping.list_lock, intSave);
}
#endif
}
......@@ -436,13 +437,9 @@ VADDR_T OsAllocSpecificRange(LosVmSpace *vmSpace, VADDR_T vaddr, size_t len, UIN
BOOL LOS_IsRegionFileValid(LosVmMapRegion *region)
{
struct file *filep = NULL;
if ((region != NULL) && (LOS_IsRegionTypeFile(region)) &&
(region->unTypeData.rf.file != NULL)) {
filep = region->unTypeData.rf.file;
if (region->unTypeData.rf.fileMagic == filep->f_magicnum) {
return TRUE;
}
(region->unTypeData.rf.vnode != NULL)) {
return TRUE;
}
return FALSE;
}
......@@ -465,6 +462,7 @@ LosVmMapRegion *OsCreateRegion(VADDR_T vaddr, size_t len, UINT32 regionFlags, un
return region;
}
memset_s(region, sizeof(LosVmMapRegion), 0, sizeof(LosVmMapRegion));
region->range.base = vaddr;
region->range.size = len;
region->pgOff = offset;
......@@ -624,6 +622,9 @@ STATUS_T LOS_RegionFree(LosVmSpace *space, LosVmMapRegion *region)
#ifdef LOSCFG_FS_VFS
if (LOS_IsRegionFileValid(region)) {
OsFilePagesRemove(space, region);
VnodeHold();
region->unTypeData.rf.vnode->useCount--;
VnodeDrop();
} else
#endif
......@@ -675,8 +676,11 @@ LosVmMapRegion *OsVmRegionDup(LosVmSpace *space, LosVmMapRegion *oldRegion, VADD
#ifdef LOSCFG_FS_VFS
if (LOS_IsRegionTypeFile(oldRegion)) {
newRegion->unTypeData.rf.vmFOps = oldRegion->unTypeData.rf.vmFOps;
newRegion->unTypeData.rf.file = oldRegion->unTypeData.rf.file;
newRegion->unTypeData.rf.fileMagic = oldRegion->unTypeData.rf.fileMagic;
newRegion->unTypeData.rf.vnode = oldRegion->unTypeData.rf.vnode;
newRegion->unTypeData.rf.f_oflags = oldRegion->unTypeData.rf.f_oflags;
VnodeHold();
newRegion->unTypeData.rf.vnode->useCount++;
VnodeDrop();
}
#endif
......
......@@ -177,7 +177,7 @@ STATIC INLINE BOOL OsProtMprotectPermCheck(unsigned long prot, LosVmMapRegion *r
{
UINT32 protFlags = 0;
UINT32 permFlags = 0;
UINT32 fileFlags = (((region->unTypeData).rf).file)->f_oflags;
UINT32 fileFlags = region->unTypeData.rf.f_oflags;
permFlags |= ((fileFlags & O_ACCMODE) ^ O_RDONLY) ? 0 : VM_MAP_REGION_FLAG_PERM_READ;
permFlags |= (fileFlags & O_WRONLY) ? VM_MAP_REGION_FLAG_PERM_WRITE : 0;
permFlags |= (fileFlags & O_RDWR) ? (VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE) : 0;
......
......@@ -89,7 +89,7 @@ typedef struct {
LD_ELF_EHDR elfEhdr;
LD_ELF_PHDR *elfPhdr;
UINT32 fileLen;
INT32 fd;
INT32 procfd;
} ELFInfo;
typedef struct {
......
......@@ -68,6 +68,24 @@ static int OsELFOpen(const CHAR *fileName, INT32 oflags)
}
AssociateSystemFd(procFd, ret);
return procFd;
}
static int OsELFClose(int procFd)
{
int ret;
/* Process procfd convert to system global procfd */
int sysfd = DisassociateProcessFd(procFd);
if (sysfd < 0) {
return -EBADF;
}
ret = close(sysfd);
if (ret < 0) {
AssociateSystemFd(procFd, sysfd);
return -get_errno();
}
FreeProcessFd(procFd);
return ret;
}
......@@ -101,10 +119,15 @@ STATIC INT32 OsGetFileLength(UINT32 *fileLen, const CHAR *fileName)
return LOS_OK;
}
STATIC INT32 OsReadELFInfo(INT32 fd, UINT8 *buffer, size_t readSize, off_t offset)
STATIC INT32 OsReadELFInfo(INT32 procfd, UINT8 *buffer, size_t readSize, off_t offset)
{
ssize_t byteNum;
off_t returnPos;
INT32 fd = GetAssociatedSystemFd(procfd);
if (fd < 0) {
PRINT_ERR("%s[%d], Invalid procfd!\n", __FUNCTION__, __LINE__);
return LOS_NOK;
}
if (readSize > 0) {
returnPos = lseek(fd, offset, SEEK_SET);
......@@ -178,8 +201,8 @@ STATIC VOID OsLoadInit(ELFLoadInfo *loadInfo)
#else
loadInfo->oldFiles = NULL;
#endif
loadInfo->execInfo.fd = INVALID_FD;
loadInfo->interpInfo.fd = INVALID_FD;
loadInfo->execInfo.procfd = INVALID_FD;
loadInfo->interpInfo.procfd = INVALID_FD;
}
STATIC INT32 OsReadEhdr(const CHAR *fileName, ELFInfo *elfInfo, BOOL isExecFile)
......@@ -196,17 +219,21 @@ STATIC INT32 OsReadEhdr(const CHAR *fileName, ELFInfo *elfInfo, BOOL isExecFile)
PRINT_ERR("%s[%d], Failed to open ELF file: %s!\n", __FUNCTION__, __LINE__, fileName);
return ret;
}
elfInfo->fd = ret;
elfInfo->procfd = ret;
#ifdef LOSCFG_DRIVERS_TZDRIVER
if (isExecFile) {
ret = fs_getfilep(elfInfo->fd, &OsCurrProcessGet()->execFile);
struct file *filep;
ret = fs_getfilep(GetAssociatedSystemFd(elfInfo->procfd), &filep);
if (ret) {
PRINT_ERR("%s[%d], Failed to get struct file %s!\n", __FUNCTION__, __LINE__, fileName);
/* File will be closed by OsLoadELFFile */
return ret;
}
OsCurrProcessGet()->execVnode = filep->f_vnode;
}
#endif
ret = OsReadELFInfo(elfInfo->fd, (UINT8 *)&elfInfo->elfEhdr, sizeof(LD_ELF_EHDR), 0);
ret = OsReadELFInfo(elfInfo->procfd, (UINT8 *)&elfInfo->elfEhdr, sizeof(LD_ELF_EHDR), 0);
if (ret != LOS_OK) {
PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__);
return -EIO;
......@@ -246,7 +273,7 @@ STATIC INT32 OsReadPhdrs(ELFInfo *elfInfo, BOOL isExecFile)
return -ENOMEM;
}
ret = OsReadELFInfo(elfInfo->fd, (UINT8 *)elfInfo->elfPhdr, size, elfEhdr->elfPhoff);
ret = OsReadELFInfo(elfInfo->procfd, (UINT8 *)elfInfo->elfPhdr, size, elfEhdr->elfPhoff);
if (ret != LOS_OK) {
(VOID)LOS_MemFree(m_aucSysMem0, elfInfo->elfPhdr);
elfInfo->elfPhdr = NULL;
......@@ -287,7 +314,7 @@ STATIC INT32 OsReadInterpInfo(ELFLoadInfo *loadInfo)
return -ENOMEM;
}
ret = OsReadELFInfo(loadInfo->execInfo.fd, (UINT8 *)elfInterpName, elfPhdr->fileSize, elfPhdr->offset);
ret = OsReadELFInfo(loadInfo->execInfo.procfd, (UINT8 *)elfInterpName, elfPhdr->fileSize, elfPhdr->offset);
if (ret != LOS_OK) {
PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__);
ret = -EIO;
......@@ -450,13 +477,14 @@ STATIC INT32 OsSetBss(const LD_ELF_PHDR *elfPhdr, INT32 fd, UINTPTR bssStart, UI
return LOS_OK;
}
STATIC INT32 OsMmapELFFile(INT32 fd, const LD_ELF_PHDR *elfPhdr, const LD_ELF_EHDR *elfEhdr, UINTPTR *elfLoadAddr,
STATIC INT32 OsMmapELFFile(INT32 procfd, const LD_ELF_PHDR *elfPhdr, const LD_ELF_EHDR *elfEhdr, UINTPTR *elfLoadAddr,
UINT32 mapSize, UINTPTR *loadBase)
{
const LD_ELF_PHDR *elfPhdrTemp = elfPhdr;
UINTPTR vAddr, mapAddr, bssStart;
UINT32 bssEnd, elfProt, elfFlags;
INT32 ret, i;
INT32 fd = GetAssociatedSystemFd(procfd);
for (i = 0; i < elfEhdr->elfPhNum; ++i, ++elfPhdrTemp) {
if (elfPhdrTemp->type != LD_PT_LOAD) {
......@@ -510,7 +538,7 @@ STATIC INT32 OsMmapELFFile(INT32 fd, const LD_ELF_PHDR *elfPhdr, const LD_ELF_EH
return LOS_OK;
}
STATIC INT32 OsLoadInterpBinary(const ELFLoadInfo *loadInfo, UINTPTR *interpMapBase)
STATIC INT32 OsLoadInterpBinary(ELFLoadInfo *loadInfo, UINTPTR *interpMapBase)
{
UINTPTR loadBase = 0;
UINT32 mapSize;
......@@ -522,14 +550,13 @@ STATIC INT32 OsLoadInterpBinary(const ELFLoadInfo *loadInfo, UINTPTR *interpMapB
return -EINVAL;
}
ret = OsMmapELFFile(loadInfo->interpInfo.fd, loadInfo->interpInfo.elfPhdr, &loadInfo->interpInfo.elfEhdr,
ret = OsMmapELFFile(loadInfo->interpInfo.procfd, loadInfo->interpInfo.elfPhdr, &loadInfo->interpInfo.elfEhdr,
interpMapBase, mapSize, &loadBase);
if (ret != LOS_OK) {
PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__);
return ret;
}
return LOS_OK;
return ret;
}
STATIC CHAR *OsGetParamPtr(CHAR * const *ptr, INT32 index)
......@@ -911,15 +938,19 @@ STATIC INT32 OsLoadELFSegment(ELFLoadInfo *loadInfo)
}
}
ret = OsMmapELFFile(loadInfo->execInfo.fd, loadInfo->execInfo.elfPhdr, &loadInfo->execInfo.elfEhdr,
ret = OsMmapELFFile(loadInfo->execInfo.procfd, loadInfo->execInfo.elfPhdr, &loadInfo->execInfo.elfEhdr,
&loadInfo->loadAddr, mapSize, &loadBase);
OsELFClose(loadInfo->execInfo.procfd);
loadInfo->execInfo.procfd = INVALID_FD;
if (ret != LOS_OK) {
PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__);
return ret;
}
if (loadInfo->interpInfo.fd != INVALID_FD) {
if (loadInfo->interpInfo.procfd != INVALID_FD) {
ret = OsLoadInterpBinary(loadInfo, &interpMapBase);
OsELFClose(loadInfo->interpInfo.procfd);
loadInfo->interpInfo.procfd = INVALID_FD;
if (ret != LOS_OK) {
return ret;
}
......@@ -974,12 +1005,12 @@ STATIC VOID OsDeInitLoadInfo(ELFLoadInfo *loadInfo)
STATIC VOID OsDeInitFiles(ELFLoadInfo *loadInfo)
{
if (loadInfo->execInfo.fd != INVALID_FD) {
(VOID)close(loadInfo->execInfo.fd);
if (loadInfo->execInfo.procfd != INVALID_FD) {
(VOID)OsELFClose(loadInfo->execInfo.procfd);
}
if (loadInfo->interpInfo.fd != INVALID_FD) {
(VOID)close(loadInfo->interpInfo.fd);
if (loadInfo->interpInfo.procfd != INVALID_FD) {
(VOID)OsELFClose(loadInfo->interpInfo.procfd);
}
#ifdef LOSCFG_FS_VFS
delete_files_snapshot((struct files_struct *)loadInfo->oldFiles);
......
......@@ -1044,39 +1044,24 @@ STATIC INT32 OsConsoleFileInit(CONSOLE_CB *consoleCB)
INT32 ret;
struct Vnode *vnode = NULL;
struct file *filep = NULL;
CHAR *fullpath = NULL;
ret = vfs_normalize_path(NULL, consoleCB->name, &fullpath);
if (ret < 0) {
return EINVAL;
}
VnodeHold();
ret = VnodeLookup(fullpath, &vnode, 0);
ret = VnodeLookup(consoleCB->name, &vnode, 0);
if (ret != LOS_OK) {
ret = EACCES;
goto ERROUT_WITH_FULLPATH;
goto ERROUT;
}
consoleCB->fd = files_allocate(vnode, O_RDWR, (off_t)0, consoleCB, STDERR_FILENO + 1);
if (consoleCB->fd < 0) {
filep = files_allocate(vnode, O_RDWR, 0, consoleCB, FILE_START_FD);
if (filep == NULL) {
ret = EMFILE;
goto ERROUT_WITH_FULLPATH;
}
ret = fs_getfilep(consoleCB->fd, &filep);
if (ret < 0) {
ret = EPERM;
goto ERROUT_WITH_FULLPATH;
goto ERROUT;
}
filep->f_path = fullpath;
filep->ops = (struct file_operations_vfs *)((struct drv_data *)vnode->data)->ops;
VnodeDrop();
return LOS_OK;
consoleCB->fd = filep->fd;
ERROUT_WITH_FULLPATH:
ERROUT:
VnodeDrop();
free(fullpath);
return ret;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册