diff --git a/fs/proc/os_adapt/fs_cache_proc.c b/fs/proc/os_adapt/fs_cache_proc.c index b026704b..146f447c 100644 --- a/fs/proc/os_adapt/fs_cache_proc.c +++ b/fs/proc/os_adapt/fs_cache_proc.c @@ -35,6 +35,11 @@ #include "los_vm_filemap.h" #ifdef LOSCFG_DEBUG_VERSION + +#define CLEAR_ALL_CACHE "clear all" +#define CLEAR_PATH_CACHE "clear pathcache" +#define CLEAR_PAGE_CACHE "clear pagecache" + static char* VnodeTypeToStr(enum VnodeType type) { switch (type) { case VNODE_TYPE_UNKNOWN: @@ -93,40 +98,39 @@ static int PathCacheListProcess(struct SeqBuf *buf) return count; } -static void PageCacheEntryProcess(struct SeqBuf *buf, struct page_mapping *mapping) +static int PageCacheEntryProcess(struct SeqBuf *buf, struct page_mapping *mapping) { + int total = 0; LosFilePage *fpage = NULL; if (mapping == NULL) { LosBufPrintf(buf, "null]\n"); - return; + return total; } LOS_DL_LIST_FOR_EACH_ENTRY(fpage, &mapping->page_list, LosFilePage, node) { LosBufPrintf(buf, "%d,", fpage->pgoff); + total++; } LosBufPrintf(buf, "]\n"); - return; + return total; } -static void PageCacheMapProcess(struct SeqBuf *buf) +static int PageCacheMapProcess(struct SeqBuf *buf) { - struct filelist *flist = &tg_filelist; - struct file *filep = NULL; + struct file_map *mapList = GetFileMappingList(); + char *name = NULL; + struct file_map *curMap = NULL; + int total = 0; - (void)sem_wait(&flist->fl_sem); - for (int i = 3; i < CONFIG_NFILE_DESCRIPTORS; i++) { - if (!get_bit(i)) { - continue; - } - filep = &flist->fl_files[i]; - if (filep == NULL) { - continue; - } - LosBufPrintf(buf, "[%d]%s:[", i, filep->f_path); - PageCacheEntryProcess(buf, filep->f_mapping); + (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); } - (void)sem_post(&flist->fl_sem); + (VOID)LOS_MuxUnlock(&mapList->lock); + return total; } static int FsCacheInfoFill(struct SeqBuf *buf, void *arg) @@ -140,6 +144,7 @@ static int FsCacheInfoFill(struct SeqBuf *buf, void *arg) int pathCacheTotalTry = 0; int pathCacheTotalHit = 0; + int pageCacheTotal = 0; int pageCacheTotalTry = 0; int pageCacheTotalHit = 0; @@ -159,19 +164,43 @@ static int FsCacheInfoFill(struct SeqBuf *buf, void *arg) pathCacheTotal = PathCacheListProcess(buf); LosBufPrintf(buf, "\n=================================================================\n"); - PageCacheMapProcess(buf); + pageCacheTotal = PageCacheMapProcess(buf); + LosBufPrintf(buf, "\n=================================================================\n"); LosBufPrintf(buf, "PathCache Total:%d Try:%d Hit:%d\n", pathCacheTotal, pathCacheTotalTry, pathCacheTotalHit); LosBufPrintf(buf, "Vnode Total:%d Free:%d Virtual:%d Active:%d\n", vnodeTotal, vnodeFree, vnodeVirtual, vnodeActive); - LosBufPrintf(buf, "PageCache Try:%d Hit:%d\n", pageCacheTotalTry, pageCacheTotalHit); + LosBufPrintf(buf, "PageCache total:%d Try:%d Hit:%d\n", pageCacheTotal, pageCacheTotalTry, pageCacheTotalHit); VnodeDrop(); return 0; } +static int FsCacheClear(struct ProcFile *pf, const char *buffer, size_t buflen, loff_t *ppos) +{ + if (buffer == NULL || buflen < sizeof(CLEAR_ALL_CACHE)) { + return -EINVAL; + } + int vnodeCount = 0; + int pageCount = 0; + + if (!strcmp(buffer, CLEAR_ALL_CACHE)) { + vnodeCount = VnodeClearCache(); + pageCount = OsTryShrinkMemory(VM_FILEMAP_MAX_SCAN); + } else if (!strcmp(buffer, CLEAR_PAGE_CACHE)) { + pageCount = OsTryShrinkMemory(VM_FILEMAP_MAX_SCAN); + } else if (!strcmp(buffer, CLEAR_PATH_CACHE)) { + vnodeCount = VnodeClearCache(); + } else { + return -EINVAL; + } + + PRINTK("%d vnodes and related pathcaches cleared\n%d pages cleared\n", vnodeCount, pageCount); + return buflen; +} static const struct ProcFileOperations FS_CACHE_PROC_FOPS = { .read = FsCacheInfoFill, + .write = FsCacheClear, }; void ProcFsCacheInit(void) diff --git a/fs/vfs/include/vnode.h b/fs/vfs/include/vnode.h index ba13e8b9..c56fbffb 100644 --- a/fs/vfs/include/vnode.h +++ b/fs/vfs/include/vnode.h @@ -179,5 +179,6 @@ int VfsVnodePermissionCheck(const struct Vnode *node, int accMode); LIST_HEAD* GetVnodeFreeList(void); LIST_HEAD* GetVnodeActiveList(void); LIST_HEAD* GetVnodeVirtualList(void); +int VnodeClearCache(void); #endif /* !_VNODE_H_ */ diff --git a/fs/vfs/operation/fs_file_mapping.c b/fs/vfs/operation/fs_file_mapping.c index 8ea8e7c7..b143df41 100644 --- a/fs/vfs/operation/fs_file_mapping.c +++ b/fs/vfs/operation/fs_file_mapping.c @@ -293,4 +293,9 @@ out: (void)sem_post(&f_list->fl_sem); return ret; } + +struct file_map* GetFileMappingList() +{ + return &g_file_mapping; +} #endif diff --git a/fs/vfs/vnode.c b/fs/vfs/vnode.c index 95bf120b..56c2ec18 100644 --- a/fs/vfs/vnode.c +++ b/fs/vfs/vnode.c @@ -640,3 +640,26 @@ LIST_HEAD* GetVnodeActiveList() { return &g_vnodeActiveList; } + +int VnodeClearCache() +{ + struct Vnode *item = NULL; + struct Vnode *nextItem = NULL; + int count = 0; + + VnodeHold(); + LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &g_vnodeActiveList, struct Vnode, actFreeEntry) { + if ((item->useCount > 0) || + (item->flag & VNODE_FLAG_MOUNT_ORIGIN) || + (item->flag & VNODE_FLAG_MOUNT_NEW)) { + continue; + } + + if (VnodeFree(item) == LOS_OK) { + count++; + } + } + VnodeDrop(); + + return count; +} diff --git a/kernel/base/include/los_vm_filemap.h b/kernel/base/include/los_vm_filemap.h index 17120118..9d8ec5fb 100644 --- a/kernel/base/include/los_vm_filemap.h +++ b/kernel/base/include/los_vm_filemap.h @@ -208,6 +208,7 @@ typedef struct ProcessCB LosProcessCB; VOID OsVmmFileRegionFree(struct file *filep, LosProcessCB *processCB); #ifdef LOSCFG_DEBUG_VERSION VOID ResetPageCacheHitInfo(int *try, int *hit); +struct file_map* GetFileMappingList(void); #endif #ifdef __cplusplus #if __cplusplus