feat: add /proc/fs_cache to display cache info

add /proc/fs_cache to display vnode, path cache, page cache.
also change some bad virable name

close: #I3WWBD

Signed-off-by: mucor <mucorwang@gmail.com>
This commit is contained in:
mucor 2021-06-21 16:11:06 +08:00
parent 7f484dfa09
commit 231cb6be27
9 changed files with 299 additions and 32 deletions

View File

@ -63,6 +63,8 @@ extern void ProcMountsInit(void);
extern void ProcUptimeInit(void);
extern void ProcFsCacheInit(void);
#ifdef __cplusplus
#if __cplusplus
}

View File

@ -0,0 +1,192 @@
/*
* Copyright (c) 2021-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 "internal.h"
#include "proc_fs.h"
#include "vnode.h"
#include "path_cache.h"
#include "los_vm_filemap.h"
#ifdef LOSCFG_DEBUG_VERSION
static char* VnodeTypeToStr(enum VnodeType type) {
switch (type) {
case VNODE_TYPE_UNKNOWN:
return "UKN";
case VNODE_TYPE_REG:
return "REG";
case VNODE_TYPE_DIR:
return "DIR";
case VNODE_TYPE_BLK:
return "BLK";
case VNODE_TYPE_CHR:
return "CHR";
case VNODE_TYPE_BCHR:
return "BCH";
case VNODE_TYPE_FIFO:
return "FIF";
case VNODE_TYPE_LNK:
return "LNK";
default:
return "BAD";
}
}
static int VnodeListProcess(struct SeqBuf *buf, LIST_HEAD* list)
{
int count = 0;
struct Vnode *item = NULL;
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",
item, item->parent, item->data, item->vop, item->hash, item->useCount,
VnodeTypeToStr(item->type), item->gid, item->uid, item->mode);
count++;
}
return count;
}
static int PathCacheListProcess(struct SeqBuf *buf)
{
int count = 0;
LIST_HEAD* bucketList = GetPathCacheList();
for (int i = 0; i < LOSCFG_MAX_PATH_CACHE_SIZE; i++) {
struct PathCache *pc = NULL;
LIST_HEAD *list = &bucketList[i];
LOS_DL_LIST_FOR_EACH_ENTRY(pc, list, struct PathCache, hashEntry) {
LosBufPrintf(buf, "%-3d %-10p %-11p %-10p %-9d %s\n", i, pc,
pc->parentVnode, pc->childVnode, pc->hit, pc->name);
count++;
}
}
return count;
}
static void PageCacheEntryProcess(struct SeqBuf *buf, struct page_mapping *mapping)
{
LosFilePage *fpage = NULL;
if (mapping == NULL) {
LosBufPrintf(buf, "null]\n");
return;
}
LOS_DL_LIST_FOR_EACH_ENTRY(fpage, &mapping->page_list, LosFilePage, node) {
LosBufPrintf(buf, "%d,", fpage->pgoff);
}
LosBufPrintf(buf, "]\n");
return;
}
static void PageCacheMapProcess(struct SeqBuf *buf)
{
struct filelist *flist = &tg_filelist;
struct file *filep = NULL;
(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)sem_post(&flist->fl_sem);
}
static int FsCacheInfoFill(struct SeqBuf *buf, void *arg)
{
int vnodeFree= 0;
int vnodeActive= 0;
int vnodeVirtual= 0;
int vnodeTotal = 0;
int pathCacheTotal = 0;
int pathCacheTotalTry = 0;
int pathCacheTotalHit = 0;
int pageCacheTotalTry = 0;
int pageCacheTotalHit = 0;
ResetPathCacheHitInfo(&pathCacheTotalHit, &pathCacheTotalTry);
ResetPageCacheHitInfo(&pageCacheTotalTry, &pageCacheTotalHit);
VnodeHold();
LosBufPrintf(buf, "\n=================================================================\n");
LosBufPrintf(buf, "VnodeAddr ParentAddr DataAddr VnodeOps Hash Ref Type Gid Uid Mode\n");
vnodeVirtual = VnodeListProcess(buf, GetVnodeVirtualList());
vnodeFree = VnodeListProcess(buf, GetVnodeFreeList());
vnodeActive = VnodeListProcess(buf, GetVnodeActiveList());
vnodeTotal = vnodeVirtual + vnodeFree + vnodeActive;
LosBufPrintf(buf, "\n=================================================================\n");
LosBufPrintf(buf, "No. CacheAddr ParentAddr ChildAddr HitCount Name\n");
pathCacheTotal = PathCacheListProcess(buf);
LosBufPrintf(buf, "\n=================================================================\n");
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);
VnodeDrop();
return 0;
}
static const struct ProcFileOperations FS_CACHE_PROC_FOPS = {
.read = FsCacheInfoFill,
};
void ProcFsCacheInit(void)
{
struct ProcDirEntry *pde = CreateProcEntry("fs_cache", 0, NULL);
if (pde == NULL) {
PRINT_ERR("create fs_cache error!\n");
return;
}
pde->procFileOps = &FS_CACHE_PROC_FOPS;
}
#else
void ProcFsCacheInit(void)
{
/* do nothing in release version */
}
#endif

View File

@ -64,6 +64,7 @@ void ProcFsInit(void)
ProcProcessInit();
ProcUptimeInit();
ProcKernelTraceInit();
ProcFsCacheInit();
}
LOS_MODULE_INIT(ProcFsInit, LOS_INIT_LEVEL_KMOD_EXTENDED);

View File

@ -42,6 +42,9 @@ struct PathCache {
LIST_ENTRY childEntry; /* list entry for cache list in the child vnode */
LIST_ENTRY hashEntry; /* list entry for buckets in the hash table */
uint8_t nameLen; /* length of path component */
#ifdef LOSCFG_DEBUG_VERSION
int hit; /* cache hit count*/
#endif
char name[0]; /* path component name */
};
@ -52,5 +55,9 @@ int PathCacheLookup(struct Vnode *parent, const char *name, int len, struct Vnod
void VnodePathCacheFree(struct Vnode *vnode);
void PathCacheMemoryDump(void);
void PathCacheDump(void);
LIST_HEAD* GetPathCacheList(void);
#ifdef LOSCFG_DEBUG_VERSION
void ResetPathCacheHitInfo(int *hit, int *try);
#endif
#endif /* _PATH_CACHE_H */

View File

@ -176,5 +176,8 @@ void VnodeMemoryDump(void);
mode_t GetUmask(void);
int VfsPermissionCheck(uint fuid, uint fgid, mode_t fileMode, int accMode);
int VfsVnodePermissionCheck(const struct Vnode *node, int accMode);
LIST_HEAD* GetVnodeFreeList(void);
LIST_HEAD* GetVnodeActiveList(void);
LIST_HEAD* GetVnodeVirtualList(void);
#endif /* !_VNODE_H_ */

View File

@ -37,6 +37,23 @@
#define PATH_CACHE_HASH_MASK (LOSCFG_MAX_PATH_CACHE_SIZE - 1)
LIST_HEAD g_pathCacheHashEntrys[LOSCFG_MAX_PATH_CACHE_SIZE];
#ifdef LOSCFG_DEBUG_VERSION
static int g_totalPathCacheHit = 0;
static int g_totalPathCacheTry = 0;
#define TRACE_TRY_CACHE() do { g_totalPathCacheTry++; } while (0)
#define TRACE_HIT_CACHE(pc) do { pc->hit++; g_totalPathCacheHit++; } while (0)
void ResetPathCacheHitInfo(int *hit, int *try)
{
*hit = g_totalPathCacheHit;
*try = g_totalPathCacheTry;
g_totalPathCacheHit = 0;
g_totalPathCacheTry = 0;
}
#else
#define TRACE_TRY_CACHE()
#define TRACE_HIT_CACHE(pc)
#endif
int PathCacheInit(void)
{
@ -50,12 +67,12 @@ void PathCacheDump(void)
{
PRINTK("-------->pathCache dump in\n");
for (int i = 0; i < LOSCFG_MAX_PATH_CACHE_SIZE; i++) {
struct PathCache *nc = NULL;
struct PathCache *pc = NULL;
LIST_HEAD *nhead = &g_pathCacheHashEntrys[i];
LOS_DL_LIST_FOR_EACH_ENTRY(nc, nhead, struct PathCache, hashEntry) {
LOS_DL_LIST_FOR_EACH_ENTRY(pc, nhead, struct PathCache, hashEntry) {
PRINTK(" pathCache dump hash %d item %s %p %p %d\n", i,
nc->name, nc->parentVnode, nc->childVnode, nc->nameLen);
pc->name, pc->parentVnode, pc->childVnode, pc->nameLen);
}
}
PRINTK("-------->pathCache dump out\n");
@ -94,7 +111,7 @@ static void PathCacheInsert(struct Vnode *parent, struct PathCache *cache, const
struct PathCache *PathCacheAlloc(struct Vnode *parent, struct Vnode *vnode, const char *name, uint8_t len)
{
struct PathCache *nc = NULL;
struct PathCache *pc = NULL;
size_t pathCacheSize;
int ret;
@ -103,53 +120,55 @@ struct PathCache *PathCacheAlloc(struct Vnode *parent, struct Vnode *vnode, cons
}
pathCacheSize = sizeof(struct PathCache) + len + 1;
nc = (struct PathCache*)zalloc(pathCacheSize);
if (nc == NULL) {
pc = (struct PathCache*)zalloc(pathCacheSize);
if (pc == NULL) {
PRINT_ERR("pathCache alloc failed, no memory!\n");
return NULL;
}
ret = strncpy_s(nc->name, len + 1, name, len);
ret = strncpy_s(pc->name, len + 1, name, len);
if (ret != LOS_OK) {
return NULL;
}
nc->parentVnode = parent;
nc->nameLen = len;
nc->childVnode = vnode;
pc->parentVnode = parent;
pc->nameLen = len;
pc->childVnode = vnode;
LOS_ListAdd((&(parent->childPathCaches)), (&(nc->childEntry)));
LOS_ListAdd((&(vnode->parentPathCaches)), (&(nc->parentEntry)));
LOS_ListAdd((&(parent->childPathCaches)), (&(pc->childEntry)));
LOS_ListAdd((&(vnode->parentPathCaches)), (&(pc->parentEntry)));
PathCacheInsert(parent, nc, name, len);
PathCacheInsert(parent, pc, name, len);
return nc;
return pc;
}
int PathCacheFree(struct PathCache *nc)
int PathCacheFree(struct PathCache *pc)
{
if (nc == NULL) {
if (pc == NULL) {
PRINT_ERR("pathCache free: invalid pathCache\n");
return -ENOENT;
}
LOS_ListDelete(&nc->hashEntry);
LOS_ListDelete(&nc->parentEntry);
LOS_ListDelete(&nc->childEntry);
free(nc);
LOS_ListDelete(&pc->hashEntry);
LOS_ListDelete(&pc->parentEntry);
LOS_ListDelete(&pc->childEntry);
free(pc);
return LOS_OK;
}
int PathCacheLookup(struct Vnode *parent, const char *name, int len, struct Vnode **vnode)
{
struct PathCache *nc = NULL;
struct PathCache *pc = NULL;
int hash = NameHash(name, len, parent) & PATH_CACHE_HASH_MASK;
LIST_HEAD *dhead = &g_pathCacheHashEntrys[hash];
LOS_DL_LIST_FOR_EACH_ENTRY(nc, dhead, struct PathCache, hashEntry) {
if (nc->parentVnode == parent && nc->nameLen == len && !strncmp(nc->name, name, len)) {
*vnode = nc->childVnode;
TRACE_TRY_CACHE();
LOS_DL_LIST_FOR_EACH_ENTRY(pc, dhead, struct PathCache, hashEntry) {
if (pc->parentVnode == parent && pc->nameLen == len && !strncmp(pc->name, name, len)) {
*vnode = pc->childVnode;
TRACE_HIT_CACHE(pc);
return LOS_OK;
}
}
@ -184,3 +203,8 @@ void VnodePathCacheFree(struct Vnode *vnode)
FreeParentPathCache(vnode);
FreeChildPathCache(vnode);
}
LIST_HEAD* GetPathCacheList()
{
return g_pathCacheHashEntrys;
}

View File

@ -35,7 +35,7 @@
LIST_HEAD g_vnodeFreeList; /* free vnodes list */
LIST_HEAD g_vnodeVirtualList; /* dev vnodes list */
LIST_HEAD g_vnodeCurrList; /* inuse vnodes list */
LIST_HEAD g_vnodeActiveList; /* inuse vnodes list */
static int g_freeVnodeSize = 0; /* system free vnodes size */
static int g_totalVnodeSize = 0; /* total vnode size */
@ -57,7 +57,7 @@ int VnodesInit(void)
LOS_ListInit(&g_vnodeFreeList);
LOS_ListInit(&g_vnodeVirtualList);
LOS_ListInit(&g_vnodeCurrList);
LOS_ListInit(&g_vnodeActiveList);
retval = VnodeAlloc(NULL, &g_rootVnode);
if (retval != LOS_OK) {
PRINT_ERR("VnodeInit failed error %d\n", retval);
@ -94,7 +94,7 @@ struct Vnode *VnodeReclaimLru(void)
struct Vnode *nextItem = NULL;
int releaseCount = 0;
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &g_vnodeCurrList, struct Vnode, actFreeEntry) {
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)) {
@ -152,7 +152,7 @@ int VnodeAlloc(struct VnodeOps *vop, struct Vnode **newVnode)
LOS_ListAdd(&g_vnodeVirtualList, &(vnode->actFreeEntry));
vnode->vop = &g_devfsOps;
} else {
LOS_ListTailInsert(&g_vnodeCurrList, &(vnode->actFreeEntry));
LOS_ListTailInsert(&g_vnodeActiveList, &(vnode->actFreeEntry));
vnode->vop = vop;
}
VnodeDrop();
@ -204,7 +204,7 @@ int VnodeFreeAll(const struct Mount *mount)
struct Vnode *nextVnode = NULL;
int ret;
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(vnode, nextVnode, &g_vnodeCurrList, struct Vnode, actFreeEntry) {
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(vnode, nextVnode, &g_vnodeActiveList, struct Vnode, actFreeEntry) {
if ((vnode->originMount == mount) && !(vnode->flag & VNODE_FLAG_MOUNT_NEW)) {
ret = VnodeFree(vnode);
if (ret != LOS_OK) {
@ -220,7 +220,7 @@ BOOL VnodeInUseIter(const struct Mount *mount)
{
struct Vnode *vnode = NULL;
LOS_DL_LIST_FOR_EACH_ENTRY(vnode, &g_vnodeCurrList, struct Vnode, actFreeEntry) {
LOS_DL_LIST_FOR_EACH_ENTRY(vnode, &g_vnodeActiveList, struct Vnode, actFreeEntry) {
if (vnode->originMount == mount) {
if ((vnode->useCount > 0) || (vnode->flag & VNODE_FLAG_MOUNT_ORIGIN)) {
return TRUE;
@ -294,7 +294,7 @@ static void RefreshLRU(struct Vnode *vnode)
return;
}
LOS_ListDelete(&(vnode->actFreeEntry));
LOS_ListTailInsert(&g_vnodeCurrList, &(vnode->actFreeEntry));
LOS_ListTailInsert(&g_vnodeActiveList, &(vnode->actFreeEntry));
}
static int ProcessVirtualVnode(struct Vnode *parent, uint32_t flags, struct Vnode **vnode)
@ -612,7 +612,7 @@ void VnodeMemoryDump(void)
struct Vnode *nextItem = NULL;
int vnodeCount = 0;
LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &g_vnodeCurrList, struct Vnode, actFreeEntry) {
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)) {
@ -625,3 +625,18 @@ void VnodeMemoryDump(void)
PRINTK("Vnode number = %d\n", vnodeCount);
PRINTK("Vnode memory size = %d(B)\n", vnodeCount * sizeof(struct Vnode));
}
LIST_HEAD* GetVnodeFreeList()
{
return &g_vnodeFreeList;
}
LIST_HEAD* GetVnodeVirtualList()
{
return &g_vnodeVirtualList;
}
LIST_HEAD* GetVnodeActiveList()
{
return &g_vnodeActiveList;
}

View File

@ -206,6 +206,9 @@ VOID OsMarkPageDirty(LosFilePage *fpage, LosVmMapRegion *region, int off, int le
typedef struct ProcessCB LosProcessCB;
VOID OsVmmFileRegionFree(struct file *filep, LosProcessCB *processCB);
#ifdef LOSCFG_DEBUG_VERSION
VOID ResetPageCacheHitInfo(int *try, int *hit);
#endif
#ifdef __cplusplus
#if __cplusplus
}

View File

@ -47,6 +47,24 @@
#define UNUSED(x) (VOID)x
#endif
#ifdef LOSCFG_DEBUG_VERSION
static int g_totalPageCacheTry = 0;
static int g_totalPageCacheHit = 0;
#define TRACE_TRY_CACHE() do { g_totalPageCacheTry++; } while (0)
#define TRACE_HIT_CACHE() do { g_totalPageCacheHit++; } while (0)
VOID ResetPageCacheHitInfo(int *try, int *hit)
{
*try = g_totalPageCacheTry;
*hit = g_totalPageCacheHit;
g_totalPageCacheHit = 0;
g_totalPageCacheTry = 0;
}
#else
#define TRACE_TRY_CACHE()
#define TRACE_HIT_CACHE()
#endif
#ifdef LOSCFG_KERNEL_VM
STATIC VOID OsPageCacheAdd(LosFilePage *page, struct page_mapping *mapping, VM_OFFSET_T pgoff)
@ -365,7 +383,9 @@ INT32 OsVmmFileFault(LosVmMapRegion *region, LosVmPgFault *vmf)
/* get or create a new cache node */
LOS_SpinLockSave(&mapping->list_lock, &intSave);
fpage = OsFindGetEntry(mapping, vmf->pgoff);
TRACE_TRY_CACHE();
if (fpage != NULL) {
TRACE_HIT_CACHE();
OsPageRefIncLocked(fpage);
} else {
fpage = OsPageCacheAlloc(mapping, vmf->pgoff);