2021-06-21 16:11:06 +08:00
|
|
|
/*
|
|
|
|
* 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
|
2021-06-24 11:34:58 +08:00
|
|
|
|
|
|
|
#define CLEAR_ALL_CACHE "clear all"
|
|
|
|
#define CLEAR_PATH_CACHE "clear pathcache"
|
|
|
|
#define CLEAR_PAGE_CACHE "clear pagecache"
|
|
|
|
|
2021-07-30 16:59:19 +08:00
|
|
|
static char* VnodeTypeToStr(enum VnodeType type)
|
|
|
|
{
|
2021-06-21 16:11:06 +08:00
|
|
|
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) {
|
2021-08-05 19:53:57 +08:00
|
|
|
LosBufPrintf(buf, "%-10p %-10p %-10p %10p 0x%08x %-3d %-4s %-3d %-3d %-8o\t%s\n",
|
2021-06-21 16:11:06 +08:00
|
|
|
item, item->parent, item->data, item->vop, item->hash, item->useCount,
|
2021-08-05 19:53:57 +08:00
|
|
|
VnodeTypeToStr(item->type), item->gid, item->uid, item->mode, item->filePath);
|
2021-06-21 16:11:06 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2021-06-24 11:34:58 +08:00
|
|
|
static int PageCacheEntryProcess(struct SeqBuf *buf, struct page_mapping *mapping)
|
2021-06-21 16:11:06 +08:00
|
|
|
{
|
2021-06-24 11:34:58 +08:00
|
|
|
int total = 0;
|
2021-06-21 16:11:06 +08:00
|
|
|
LosFilePage *fpage = NULL;
|
|
|
|
|
2021-08-05 19:53:57 +08:00
|
|
|
if (mapping->nrpages == 0) {
|
2021-06-21 16:11:06 +08:00
|
|
|
LosBufPrintf(buf, "null]\n");
|
2021-06-24 11:34:58 +08:00
|
|
|
return total;
|
2021-06-21 16:11:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
LOS_DL_LIST_FOR_EACH_ENTRY(fpage, &mapping->page_list, LosFilePage, node) {
|
|
|
|
LosBufPrintf(buf, "%d,", fpage->pgoff);
|
2021-06-24 11:34:58 +08:00
|
|
|
total++;
|
2021-06-21 16:11:06 +08:00
|
|
|
}
|
|
|
|
LosBufPrintf(buf, "]\n");
|
2021-06-24 11:34:58 +08:00
|
|
|
return total;
|
2021-06-21 16:11:06 +08:00
|
|
|
}
|
|
|
|
|
2021-06-24 11:34:58 +08:00
|
|
|
static int PageCacheMapProcess(struct SeqBuf *buf)
|
2021-06-21 16:11:06 +08:00
|
|
|
{
|
2021-08-05 19:53:57 +08:00
|
|
|
LIST_HEAD *vnodeList = GetVnodeActiveList();
|
|
|
|
struct page_mapping *mapping = NULL;
|
|
|
|
struct Vnode *vnode = NULL;
|
2021-06-24 11:34:58 +08:00
|
|
|
int total = 0;
|
|
|
|
|
2021-08-05 19:53:57 +08:00
|
|
|
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);
|
2021-06-21 16:11:06 +08:00
|
|
|
}
|
2021-08-05 19:53:57 +08:00
|
|
|
VnodeDrop();
|
2021-06-24 11:34:58 +08:00
|
|
|
return total;
|
2021-06-21 16:11:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int FsCacheInfoFill(struct SeqBuf *buf, void *arg)
|
|
|
|
{
|
2021-07-30 16:59:19 +08:00
|
|
|
int vnodeFree = 0;
|
|
|
|
int vnodeActive = 0;
|
|
|
|
int vnodeVirtual = 0;
|
2021-06-21 16:11:06 +08:00
|
|
|
int vnodeTotal = 0;
|
|
|
|
|
|
|
|
int pathCacheTotal = 0;
|
|
|
|
int pathCacheTotalTry = 0;
|
|
|
|
int pathCacheTotalHit = 0;
|
|
|
|
|
2021-06-24 11:34:58 +08:00
|
|
|
int pageCacheTotal = 0;
|
2021-06-21 16:11:06 +08:00
|
|
|
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");
|
2021-06-24 11:34:58 +08:00
|
|
|
pageCacheTotal = PageCacheMapProcess(buf);
|
|
|
|
|
2021-06-21 16:11:06 +08:00
|
|
|
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);
|
2021-06-24 11:34:58 +08:00
|
|
|
LosBufPrintf(buf, "PageCache total:%d Try:%d Hit:%d\n", pageCacheTotal, pageCacheTotalTry, pageCacheTotalHit);
|
2021-06-21 16:11:06 +08:00
|
|
|
VnodeDrop();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-06-24 11:34:58 +08:00
|
|
|
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;
|
|
|
|
}
|
2021-06-21 16:11:06 +08:00
|
|
|
static const struct ProcFileOperations FS_CACHE_PROC_FOPS = {
|
|
|
|
.read = FsCacheInfoFill,
|
2021-06-24 11:34:58 +08:00
|
|
|
.write = FsCacheClear,
|
2021-06-21 16:11:06 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
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
|