From 38a6b804e9291d2fdbd189825ebd7d56165ec51c Mon Sep 17 00:00:00 2001 From: Leon Chan Date: Thu, 5 Aug 2021 19:53:57 +0800 Subject: [PATCH] feat: page cache backed by vnode instead of filep 1, change the owner of page to vnode 2, save the file path in vnode close: #I44TBS Signed-off-by: Leon Chan --- arch/arm/arm/src/los_exc.c | 10 +- fs/fat/os_adapt/fatfs.c | 204 ++++++++++++++ fs/include/fs/fs_operation.h | 75 ----- fs/jffs2/src/vfs_jffs2.c | 84 +++++- fs/proc/os_adapt/fs_cache_proc.c | 24 +- fs/vfs/BUILD.gn | 1 - fs/vfs/include/vnode.h | 4 + fs/vfs/operation/vfs_file_mapping.c | 303 --------------------- fs/vfs/operation/vfs_init.c | 9 +- fs/vfs/vnode.c | 37 ++- kernel/base/include/los_vm_map.h | 6 +- kernel/base/vm/los_vm_dump.c | 7 +- kernel/base/vm/los_vm_fault.c | 44 +-- kernel/base/vm/los_vm_filemap.c | 116 +++----- kernel/base/vm/los_vm_map.c | 26 +- kernel/base/vm/los_vm_syscall.c | 2 +- kernel/common/console.c | 29 +- kernel/extended/dynload/src/los_load_elf.c | 9 +- 18 files changed, 446 insertions(+), 544 deletions(-) delete mode 100644 fs/vfs/operation/vfs_file_mapping.c diff --git a/arch/arm/arm/src/los_exc.c b/arch/arm/arm/src/los_exc.c index 297a061b..138afdf5 100644 --- a/arch/arm/arm/src/los_exc.c +++ b/arch/arm/arm/src/los_exc.c @@ -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 diff --git a/fs/fat/os_adapt/fatfs.c b/fs/fat/os_adapt/fatfs.c index 51b1adaf..8b2df0a2 100644 --- a/fs/fat/os_adapt/fatfs.c +++ b/fs/fat/os_adapt/fatfs.c @@ -48,6 +48,7 @@ #include "user_copy.h" #include "los_vm_filemap.h" #include "los_hash.h" +#include "los_vm_common.h" #include #include #include @@ -2204,6 +2205,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, @@ -2211,6 +2413,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, diff --git a/fs/include/fs/fs_operation.h b/fs/include/fs/fs_operation.h index 2b99cb0b..b96f0c77 100644 --- a/fs/include/fs/fs_operation.h +++ b/fs/include/fs/fs_operation.h @@ -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 diff --git a/fs/jffs2/src/vfs_jffs2.c b/fs/jffs2/src/vfs_jffs2.c index 7ae10bed..8a7498db 100644 --- a/fs/jffs2/src/vfs_jffs2.c +++ b/fs/jffs2/src/vfs_jffs2.c @@ -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, diff --git a/fs/proc/os_adapt/fs_cache_proc.c b/fs/proc/os_adapt/fs_cache_proc.c index b9e4d7b5..9ba8917c 100644 --- a/fs/proc/os_adapt/fs_cache_proc.c +++ b/fs/proc/os_adapt/fs_cache_proc.c @@ -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; } diff --git a/fs/vfs/BUILD.gn b/fs/vfs/BUILD.gn index 5ef3b80f..71159a7e 100644 --- a/fs/vfs/BUILD.gn +++ b/fs/vfs/BUILD.gn @@ -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", diff --git a/fs/vfs/include/vnode.h b/fs/vfs/include/vnode.h index 83990fe5..169a0915 100644 --- a/fs/vfs/include/vnode.h +++ b/fs/vfs/include/vnode.h @@ -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); diff --git a/fs/vfs/operation/vfs_file_mapping.c b/fs/vfs/operation/vfs_file_mapping.c deleted file mode 100644 index 8842579f..00000000 --- a/fs/vfs/operation/vfs_file_mapping.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * 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 diff --git a/fs/vfs/operation/vfs_init.c b/fs/vfs/operation/vfs_init.c index dcaf2fd8..fbb88a07 100644 --- a/fs/vfs/operation/vfs_init.c +++ b/fs/vfs/operation/vfs_init.c @@ -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; } diff --git a/fs/vfs/vnode.c b/fs/vfs/vnode.c index 056720d1..28213d16 100644 --- a/fs/vfs/vnode.c +++ b/fs/vfs/vnode.c @@ -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,10 @@ 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; + } + return ret; } else if (VfsVnodePermissionCheck(currentVnode, EXEC_OP)) { ret = -EACCES; goto OUT_FREE_PATH; @@ -401,13 +415,29 @@ 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; + } } + return ret; OUT_FREE_PATH: if (normalizedPath) { free(normalizedPath); } - return ret; } @@ -534,6 +564,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; diff --git a/kernel/base/include/los_vm_map.h b/kernel/base/include/los_vm_map.h index e601c5cd..18864d81 100644 --- a/kernel/base/include/los_vm_map.h +++ b/kernel/base/include/los_vm_map.h @@ -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 { diff --git a/kernel/base/vm/los_vm_dump.c b/kernel/base/vm/los_vm_dump.c index a0da5669..83ef92b4 100644 --- a/kernel/base/vm/los_vm_dump.c +++ b/kernel/base/vm/los_vm_dump.c @@ -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"; diff --git a/kernel/base/vm/los_vm_fault.c b/kernel/base/vm/los_vm_fault.c index d8f61b27..ead6eff0 100644 --- a/kernel/base/vm/los_vm_fault.c +++ b/kernel/base/vm/los_vm_fault.c @@ -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(®ion->unTypeData.rf.file->f_mapping->mux_lock); + (VOID)LOS_MuxAcquire(®ion->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(®ion->unTypeData.rf.file->f_mapping->mux_lock); + (VOID)LOS_MuxRelease(®ion->unTypeData.rf.vnode->mapping.mux_lock); return LOS_ERRNO_VM_NO_MEMORY; } - (VOID)LOS_MuxRelease(®ion->unTypeData.rf.file->f_mapping->mux_lock); + (VOID)LOS_MuxRelease(®ion->unTypeData.rf.vnode->mapping.mux_lock); return LOS_OK; } - (VOID)LOS_MuxRelease(®ion->unTypeData.rf.file->f_mapping->mux_lock); + (VOID)LOS_MuxRelease(®ion->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(®ion->unTypeData.rf.file->f_mapping->list_lock, &intSave); - fpage = OsFindGetEntry(region->unTypeData.rf.file->f_mapping, vmf->pgoff); + LOS_SpinLockSave(®ion->unTypeData.rf.vnode->mapping.list_lock, &intSave); + fpage = OsFindGetEntry(®ion->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(®ion->unTypeData.rf.file->f_mapping->list_lock, intSave); + LOS_SpinUnlockRestore(®ion->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(®ion->unTypeData.rf.file->f_mapping->mux_lock); + (VOID)LOS_MuxAcquire(®ion->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(®ion->unTypeData.rf.file->f_mapping->mux_lock); + (VOID)LOS_MuxRelease(®ion->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(®ion->unTypeData.rf.file->f_mapping->mux_lock); + (VOID)LOS_MuxRelease(®ion->unTypeData.rf.vnode->mapping.mux_lock); goto ERR_OUT; } - (VOID)LOS_MuxRelease(®ion->unTypeData.rf.file->f_mapping->mux_lock); + (VOID)LOS_MuxRelease(®ion->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(®ion->unTypeData.rf.file->f_mapping->list_lock, &intSave); - fpage = OsFindGetEntry(region->unTypeData.rf.file->f_mapping, vmPgFault->pgoff); + LOS_SpinLockSave(®ion->unTypeData.rf.vnode->mapping.list_lock, &intSave); + fpage = OsFindGetEntry(®ion->unTypeData.rf.vnode->mapping, vmPgFault->pgoff); if (fpage) { OsMarkPageDirty(fpage, region, 0, 0); } - LOS_SpinUnlockRestore(®ion->unTypeData.rf.file->f_mapping->list_lock, intSave); + LOS_SpinUnlockRestore(®ion->unTypeData.rf.vnode->mapping.list_lock, intSave); return LOS_OK; } - (VOID)LOS_MuxAcquire(®ion->unTypeData.rf.file->f_mapping->mux_lock); + (VOID)LOS_MuxAcquire(®ion->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(®ion->unTypeData.rf.file->f_mapping->mux_lock); + (VOID)LOS_MuxRelease(®ion->unTypeData.rf.vnode->mapping.mux_lock); return LOS_ERRNO_VM_NO_MEMORY; } - (VOID)LOS_MuxRelease(®ion->unTypeData.rf.file->f_mapping->mux_lock); + (VOID)LOS_MuxRelease(®ion->unTypeData.rf.vnode->mapping.mux_lock); return LOS_OK; } - (VOID)LOS_MuxRelease(®ion->unTypeData.rf.file->f_mapping->mux_lock); + (VOID)LOS_MuxRelease(®ion->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; diff --git a/kernel/base/vm/los_vm_filemap.c b/kernel/base/vm/los_vm_filemap.c index 18ffe117..78ad60ac 100644 --- a/kernel/base/vm/los_vm_filemap.c +++ b/kernel/base/vm/los_vm_filemap.c @@ -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(®ion->unTypeData.rf.file->f_mapping->list_lock, &intSave); - fpage = OsFindGetEntry(region->unTypeData.rf.file->f_mapping, vmf->pgoff); + mapping = ®ion->unTypeData.rf.vnode->mapping; + LOS_SpinLockSave(&mapping->list_lock, &intSave); + fpage = OsFindGetEntry(mapping, vmf->pgoff); if (fpage == NULL) { - LOS_SpinUnlockRestore(®ion->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(®ion->unTypeData.rf.file->f_mapping->list_lock, intSave); + LOS_SpinUnlockRestore(&mapping->list_lock, intSave); LOS_MemFree(m_aucSysMem0, info); return; } - LOS_SpinUnlockRestore(®ion->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 diff --git a/kernel/base/vm/los_vm_map.c b/kernel/base/vm/los_vm_map.c index bbeb43e2..a11385f7 100644 --- a/kernel/base/vm/los_vm_map.c +++ b/kernel/base/vm/los_vm_map.c @@ -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 diff --git a/kernel/base/vm/los_vm_syscall.c b/kernel/base/vm/los_vm_syscall.c index df8b246d..2b2ac295 100644 --- a/kernel/base/vm/los_vm_syscall.c +++ b/kernel/base/vm/los_vm_syscall.c @@ -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; diff --git a/kernel/common/console.c b/kernel/common/console.c index 6f5ba830..f0bd601a 100644 --- a/kernel/common/console.c +++ b/kernel/common/console.c @@ -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; + goto ERROUT; } - - ret = fs_getfilep(consoleCB->fd, &filep); - if (ret < 0) { - ret = EPERM; - goto ERROUT_WITH_FULLPATH; - } - 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; } diff --git a/kernel/extended/dynload/src/los_load_elf.c b/kernel/extended/dynload/src/los_load_elf.c index 2844df6e..574b7f08 100644 --- a/kernel/extended/dynload/src/los_load_elf.c +++ b/kernel/extended/dynload/src/los_load_elf.c @@ -526,7 +526,7 @@ STATIC INT32 OsMmapELFFile(INT32 procfd, const LD_ELF_PHDR *elfPhdr, const LD_EL return LOS_OK; } -STATIC INT32 OsLoadInterpBinary(const ELFLoadInfo *loadInfo, UINTPTR *interpMapBase) +STATIC INT32 OsLoadInterpBinary(ELFLoadInfo *loadInfo, UINTPTR *interpMapBase) { UINTPTR loadBase = 0; UINT32 mapSize; @@ -542,10 +542,11 @@ STATIC INT32 OsLoadInterpBinary(const ELFLoadInfo *loadInfo, UINTPTR *interpMapB interpMapBase, mapSize, &loadBase); if (ret != LOS_OK) { PRINT_ERR("%s[%d]\n", __FUNCTION__, __LINE__); - return ret; } - return LOS_OK; + OsELFClose(loadInfo->interpInfo.procfd); + loadInfo->interpInfo.procfd = INVALID_FD; + return ret; } STATIC CHAR *OsGetParamPtr(CHAR * const *ptr, INT32 index) @@ -929,6 +930,8 @@ STATIC INT32 OsLoadELFSegment(ELFLoadInfo *loadInfo) 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;