• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2021 Huawei Device Co., Ltd. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without modification,
5  * are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice, this list of
8  *    conditions and the following disclaimer.
9  *
10  * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11  *    of conditions and the following disclaimer in the documentation and/or other materials
12  *    provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used
15  *    to endorse or promote products derived from this software without specific prior written
16  *    permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
25  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
27  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
28  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "internal.h"
32 #include "proc_fs.h"
33 #include "vnode.h"
34 #include "path_cache.h"
35 #include "los_vm_filemap.h"
36 
37 #ifdef LOSCFG_DEBUG_VERSION
38 
39 #define CLEAR_ALL_CACHE  "clear all"
40 #define CLEAR_PATH_CACHE "clear pathcache"
41 #define CLEAR_PAGE_CACHE "clear pagecache"
42 
VnodeTypeToStr(enum VnodeType type)43 static char* VnodeTypeToStr(enum VnodeType type)
44 {
45     switch (type) {
46         case VNODE_TYPE_UNKNOWN:
47             return "UKN";
48         case VNODE_TYPE_REG:
49             return "REG";
50         case VNODE_TYPE_DIR:
51             return "DIR";
52         case VNODE_TYPE_BLK:
53             return "BLK";
54         case VNODE_TYPE_CHR:
55             return "CHR";
56         case VNODE_TYPE_BCHR:
57             return "BCH";
58         case VNODE_TYPE_FIFO:
59             return "FIF";
60         case VNODE_TYPE_LNK:
61             return "LNK";
62         default:
63             return "BAD";
64     }
65 }
66 
VnodeListProcess(struct SeqBuf * buf,LIST_HEAD * list)67 static int VnodeListProcess(struct SeqBuf *buf, LIST_HEAD* list)
68 {
69     int count = 0;
70     struct Vnode *item = NULL;
71     struct Vnode *nextItem = NULL;
72 
73     LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, list, struct Vnode, actFreeEntry) {
74         LosBufPrintf(buf, "%-10p    %-10p     %-10p    %10p    0x%08x    %-3d    %-4s    %-3d    %-3d    %-8o\t%s\n",
75             item, item->parent, item->data, item->vop, item->hash, item->useCount,
76             VnodeTypeToStr(item->type), item->gid, item->uid, item->mode, item->filePath);
77         count++;
78     }
79 
80     return count;
81 }
82 
PathCacheListProcess(struct SeqBuf * buf)83 static int PathCacheListProcess(struct SeqBuf *buf)
84 {
85     int count = 0;
86     LIST_HEAD* bucketList = GetPathCacheList();
87 
88     for (int i = 0; i < LOSCFG_MAX_PATH_CACHE_SIZE; i++) {
89         struct PathCache *pc = NULL;
90         LIST_HEAD *list = &bucketList[i];
91 
92         LOS_DL_LIST_FOR_EACH_ENTRY(pc, list, struct PathCache, hashEntry) {
93             LosBufPrintf(buf, "%-3d    %-10p    %-11p    %-10p    %-9d    %s\n", i, pc,
94                 pc->parentVnode, pc->childVnode, pc->hit, pc->name);
95             count++;
96         }
97     }
98 
99     return count;
100 }
101 
PageCacheEntryProcess(struct SeqBuf * buf,struct page_mapping * mapping)102 static int PageCacheEntryProcess(struct SeqBuf *buf, struct page_mapping *mapping)
103 {
104     int total = 0;
105     LosFilePage *fpage = NULL;
106 
107     if (mapping->nrpages == 0) {
108         LosBufPrintf(buf, "null]\n");
109         return total;
110     }
111 
112     LOS_DL_LIST_FOR_EACH_ENTRY(fpage, &mapping->page_list, LosFilePage, node) {
113         LosBufPrintf(buf, "%d,", fpage->pgoff);
114         total++;
115     }
116     LosBufPrintf(buf, "]\n");
117     return total;
118 }
119 
PageCacheMapProcess(struct SeqBuf * buf)120 static int PageCacheMapProcess(struct SeqBuf *buf)
121 {
122     LIST_HEAD *vnodeList = GetVnodeActiveList();
123     struct page_mapping *mapping = NULL;
124     struct Vnode *vnode = NULL;
125     int total = 0;
126 
127     VnodeHold();
128     LOS_DL_LIST_FOR_EACH_ENTRY(vnode, vnodeList, struct Vnode, actFreeEntry) {
129         mapping = &vnode->mapping;
130         LosBufPrintf(buf, "%p, %s:[", vnode, vnode->filePath);
131         total += PageCacheEntryProcess(buf, mapping);
132     }
133     VnodeDrop();
134     return total;
135 }
136 
FsCacheInfoFill(struct SeqBuf * buf,void * arg)137 static int FsCacheInfoFill(struct SeqBuf *buf, void *arg)
138 {
139     int vnodeFree = 0;
140     int vnodeActive = 0;
141     int vnodeVirtual = 0;
142     int vnodeTotal = 0;
143 
144     int pathCacheTotal = 0;
145     int pathCacheTotalTry = 0;
146     int pathCacheTotalHit = 0;
147 
148     int pageCacheTotal = 0;
149     int pageCacheTotalTry = 0;
150     int pageCacheTotalHit = 0;
151 
152     ResetPathCacheHitInfo(&pathCacheTotalHit, &pathCacheTotalTry);
153     ResetPageCacheHitInfo(&pageCacheTotalTry, &pageCacheTotalHit);
154 
155     VnodeHold();
156     LosBufPrintf(buf, "\n=================================================================\n");
157     LosBufPrintf(buf, "VnodeAddr     ParentAddr     DataAddr      VnodeOps      Hash          Ref    Type    Gid    Uid    Mode\n");
158     vnodeVirtual = VnodeListProcess(buf, GetVnodeVirtualList());
159     vnodeFree = VnodeListProcess(buf, GetVnodeFreeList());
160     vnodeActive = VnodeListProcess(buf, GetVnodeActiveList());
161     vnodeTotal = vnodeVirtual + vnodeFree + vnodeActive;
162 
163     LosBufPrintf(buf, "\n=================================================================\n");
164     LosBufPrintf(buf, "No.    CacheAddr     ParentAddr     ChildAddr     HitCount     Name\n");
165     pathCacheTotal = PathCacheListProcess(buf);
166 
167     LosBufPrintf(buf, "\n=================================================================\n");
168     pageCacheTotal = PageCacheMapProcess(buf);
169 
170     LosBufPrintf(buf, "\n=================================================================\n");
171     LosBufPrintf(buf, "PathCache Total:%d Try:%d Hit:%d\n",
172         pathCacheTotal, pathCacheTotalTry, pathCacheTotalHit);
173     LosBufPrintf(buf, "Vnode Total:%d Free:%d Virtual:%d Active:%d\n",
174         vnodeTotal, vnodeFree, vnodeVirtual, vnodeActive);
175     LosBufPrintf(buf, "PageCache total:%d Try:%d Hit:%d\n", pageCacheTotal, pageCacheTotalTry, pageCacheTotalHit);
176     VnodeDrop();
177     return 0;
178 }
179 
FsCacheClear(struct ProcFile * pf,const char * buffer,size_t buflen,loff_t * ppos)180 static int FsCacheClear(struct ProcFile *pf, const char *buffer, size_t buflen, loff_t *ppos)
181 {
182     if (buffer == NULL || buflen < sizeof(CLEAR_ALL_CACHE)) {
183         return -EINVAL;
184     }
185     int vnodeCount = 0;
186     int pageCount = 0;
187 
188     if (!strcmp(buffer, CLEAR_ALL_CACHE)) {
189         vnodeCount = VnodeClearCache();
190         pageCount = OsTryShrinkMemory(VM_FILEMAP_MAX_SCAN);
191     } else if (!strcmp(buffer, CLEAR_PAGE_CACHE)) {
192         pageCount = OsTryShrinkMemory(VM_FILEMAP_MAX_SCAN);
193     } else if (!strcmp(buffer, CLEAR_PATH_CACHE)) {
194         vnodeCount = VnodeClearCache();
195     } else {
196         return -EINVAL;
197     }
198 
199     PRINTK("%d vnodes and related pathcaches cleared\n%d pages cleared\n", vnodeCount, pageCount);
200     return buflen;
201 }
202 static const struct ProcFileOperations FS_CACHE_PROC_FOPS = {
203     .read = FsCacheInfoFill,
204     .write = FsCacheClear,
205 };
206 
ProcFsCacheInit(void)207 void ProcFsCacheInit(void)
208 {
209     struct ProcDirEntry *pde = CreateProcEntry("fs_cache", 0, NULL);
210     if (pde == NULL) {
211         PRINT_ERR("create fs_cache error!\n");
212         return;
213     }
214 
215     pde->procFileOps = &FS_CACHE_PROC_FOPS;
216 }
217 #else
ProcFsCacheInit(void)218 void ProcFsCacheInit(void)
219 {
220     /* do nothing in release version */
221 }
222 #endif
223