• 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 "path_cache.h"
32 #include "los_config.h"
33 #include "los_hash.h"
34 #include "stdlib.h"
35 #include "limits.h"
36 #include "vnode.h"
37 
38 #define PATH_CACHE_HASH_MASK (LOSCFG_MAX_PATH_CACHE_SIZE - 1)
39 LIST_HEAD g_pathCacheHashEntrys[LOSCFG_MAX_PATH_CACHE_SIZE];
40 #ifdef LOSCFG_DEBUG_VERSION
41 static int g_totalPathCacheHit = 0;
42 static int g_totalPathCacheTry = 0;
43 #define TRACE_TRY_CACHE() do { g_totalPathCacheTry++; } while (0)
44 #define TRACE_HIT_CACHE(pc) do { pc->hit++; g_totalPathCacheHit++; } while (0)
45 
ResetPathCacheHitInfo(int * hit,int * try)46 void ResetPathCacheHitInfo(int *hit, int *try)
47 {
48     *hit = g_totalPathCacheHit;
49     *try = g_totalPathCacheTry;
50     g_totalPathCacheHit = 0;
51     g_totalPathCacheTry = 0;
52 }
53 #else
54 #define TRACE_TRY_CACHE()
55 #define TRACE_HIT_CACHE(pc)
56 #endif
57 
PathCacheInit(void)58 int PathCacheInit(void)
59 {
60     for (int i = 0; i < LOSCFG_MAX_PATH_CACHE_SIZE; i++) {
61         LOS_ListInit(&g_pathCacheHashEntrys[i]);
62     }
63     return LOS_OK;
64 }
65 
PathCacheDump(void)66 void PathCacheDump(void)
67 {
68     PRINTK("-------->pathCache dump in\n");
69     for (int i = 0; i < LOSCFG_MAX_PATH_CACHE_SIZE; i++) {
70         struct PathCache *pc = NULL;
71         LIST_HEAD *nhead = &g_pathCacheHashEntrys[i];
72 
73         LOS_DL_LIST_FOR_EACH_ENTRY(pc, nhead, struct PathCache, hashEntry) {
74             PRINTK("    pathCache dump hash %d item %s %p %p %d\n", i,
75                 pc->name, pc->parentVnode, pc->childVnode, pc->nameLen);
76         }
77     }
78     PRINTK("-------->pathCache dump out\n");
79 }
80 
PathCacheMemoryDump(void)81 void PathCacheMemoryDump(void)
82 {
83     int pathCacheNum = 0;
84     int nameSum = 0;
85     for (int i = 0; i < LOSCFG_MAX_PATH_CACHE_SIZE; i++) {
86         LIST_HEAD *dhead = &g_pathCacheHashEntrys[i];
87         struct PathCache *dent = NULL;
88 
89         LOS_DL_LIST_FOR_EACH_ENTRY(dent, dhead, struct PathCache, hashEntry) {
90             pathCacheNum++;
91             nameSum += dent->nameLen;
92         }
93     }
94     PRINTK("pathCache number = %d\n", pathCacheNum);
95     PRINTK("pathCache memory size = %d(B)\n", pathCacheNum * sizeof(struct PathCache) + nameSum);
96 }
97 
NameHash(const char * name,int len,struct Vnode * dvp)98 static uint32_t NameHash(const char *name, int len, struct Vnode *dvp)
99 {
100     uint32_t hash;
101     hash = LOS_HashFNV32aBuf(name, len, FNV1_32A_INIT);
102     hash = LOS_HashFNV32aBuf(&dvp, sizeof(struct Vnode *), hash);
103     return hash;
104 }
105 
PathCacheInsert(struct Vnode * parent,struct PathCache * cache,const char * name,int len)106 static void PathCacheInsert(struct Vnode *parent, struct PathCache *cache, const char* name, int len)
107 {
108     int hash = NameHash(name, len, parent) & PATH_CACHE_HASH_MASK;
109     LOS_ListAdd(&g_pathCacheHashEntrys[hash], &cache->hashEntry);
110 }
111 
PathCacheAlloc(struct Vnode * parent,struct Vnode * vnode,const char * name,uint8_t len)112 struct PathCache *PathCacheAlloc(struct Vnode *parent, struct Vnode *vnode, const char *name, uint8_t len)
113 {
114     struct PathCache *pc = NULL;
115     size_t pathCacheSize;
116     int ret;
117 
118     if (name == NULL || len > NAME_MAX || parent == NULL || vnode == NULL) {
119         return NULL;
120     }
121     pathCacheSize = sizeof(struct PathCache) + len + 1;
122 
123     pc = (struct PathCache*)zalloc(pathCacheSize);
124     if (pc == NULL) {
125         PRINT_ERR("pathCache alloc failed, no memory!\n");
126         return NULL;
127     }
128 
129     ret = strncpy_s(pc->name, len + 1, name, len);
130     if (ret != LOS_OK) {
131         free(pc);
132         return NULL;
133     }
134 
135     pc->parentVnode = parent;
136     pc->nameLen = len;
137     pc->childVnode = vnode;
138 
139     LOS_ListAdd((&(parent->childPathCaches)), (&(pc->childEntry)));
140     LOS_ListAdd((&(vnode->parentPathCaches)), (&(pc->parentEntry)));
141 
142     PathCacheInsert(parent, pc, name, len);
143 
144     return pc;
145 }
146 
PathCacheFree(struct PathCache * pc)147 int PathCacheFree(struct PathCache *pc)
148 {
149     if (pc == NULL) {
150         PRINT_ERR("pathCache free: invalid pathCache\n");
151         return -ENOENT;
152     }
153 
154     LOS_ListDelete(&pc->hashEntry);
155     LOS_ListDelete(&pc->parentEntry);
156     LOS_ListDelete(&pc->childEntry);
157     free(pc);
158 
159     return LOS_OK;
160 }
161 
PathCacheLookup(struct Vnode * parent,const char * name,int len,struct Vnode ** vnode)162 int PathCacheLookup(struct Vnode *parent, const char *name, int len, struct Vnode **vnode)
163 {
164     struct PathCache *pc = NULL;
165     int hash = NameHash(name, len, parent) & PATH_CACHE_HASH_MASK;
166     LIST_HEAD *dhead = &g_pathCacheHashEntrys[hash];
167 
168     TRACE_TRY_CACHE();
169     LOS_DL_LIST_FOR_EACH_ENTRY(pc, dhead, struct PathCache, hashEntry) {
170         if (pc->parentVnode == parent && pc->nameLen == len && !strncmp(pc->name, name, len)) {
171             *vnode = pc->childVnode;
172             TRACE_HIT_CACHE(pc);
173             return LOS_OK;
174         }
175     }
176     return -ENOENT;
177 }
178 
FreeChildPathCache(struct Vnode * vnode)179 static void FreeChildPathCache(struct Vnode *vnode)
180 {
181     struct PathCache *item = NULL;
182     struct PathCache *nextItem = NULL;
183 
184     LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &(vnode->childPathCaches), struct PathCache, childEntry) {
185         PathCacheFree(item);
186     }
187 }
188 
FreeParentPathCache(struct Vnode * vnode)189 static void FreeParentPathCache(struct Vnode *vnode)
190 {
191     struct PathCache *item = NULL;
192     struct PathCache *nextItem = NULL;
193 
194     LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &(vnode->parentPathCaches), struct PathCache, parentEntry) {
195         PathCacheFree(item);
196     }
197 }
198 
VnodePathCacheFree(struct Vnode * vnode)199 void VnodePathCacheFree(struct Vnode *vnode)
200 {
201     if (vnode == NULL) {
202         return;
203     }
204     FreeParentPathCache(vnode);
205     FreeChildPathCache(vnode);
206 }
207 
GetPathCacheList()208 LIST_HEAD* GetPathCacheList()
209 {
210     return g_pathCacheHashEntrys;
211 }
212