• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 "los_mux.h"
32 #include "vnode.h"
33 #include "fs/dirent_fs.h"
34 #include "path_cache.h"
35 
36 LIST_HEAD g_vnodeFreeList;              /* free vnodes list */
37 LIST_HEAD g_vnodeVirtualList;           /* dev vnodes list */
38 LIST_HEAD g_vnodeActiveList;              /* inuse vnodes list */
39 static int g_freeVnodeSize = 0;         /* system free vnodes size */
40 static int g_totalVnodeSize = 0;        /* total vnode size */
41 
42 static LosMux g_vnodeMux;
43 static struct Vnode *g_rootVnode = NULL;
44 static struct VnodeOps g_devfsOps;
45 
46 #define ENTRY_TO_VNODE(ptr)  LOS_DL_LIST_ENTRY(ptr, struct Vnode, actFreeEntry)
47 #define VNODE_LRU_COUNT      10
48 #define DEV_VNODE_MODE       0755
49 
VnodesInit(void)50 int VnodesInit(void)
51 {
52     int retval = LOS_MuxInit(&g_vnodeMux, NULL);
53     if (retval != LOS_OK) {
54         PRINT_ERR("Create mutex for vnode fail, status: %d", retval);
55         return retval;
56     }
57 
58     LOS_ListInit(&g_vnodeFreeList);
59     LOS_ListInit(&g_vnodeVirtualList);
60     LOS_ListInit(&g_vnodeActiveList);
61     retval = VnodeAlloc(NULL, &g_rootVnode);
62     if (retval != LOS_OK) {
63         PRINT_ERR("VnodeInit failed error %d\n", retval);
64         return retval;
65     }
66     g_rootVnode->mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR;
67     g_rootVnode->type = VNODE_TYPE_DIR;
68     g_rootVnode->filePath = "/";
69 
70     return LOS_OK;
71 }
72 
GetFromFreeList(void)73 static struct Vnode *GetFromFreeList(void)
74 {
75     if (g_freeVnodeSize <= 0) {
76         return NULL;
77     }
78     struct Vnode *vnode = NULL;
79 
80     if (LOS_ListEmpty(&g_vnodeFreeList)) {
81         PRINT_ERR("get vnode from free list failed, list empty but g_freeVnodeSize = %d!\n", g_freeVnodeSize);
82         g_freeVnodeSize = 0;
83         return NULL;
84     }
85 
86     vnode = ENTRY_TO_VNODE(LOS_DL_LIST_FIRST(&g_vnodeFreeList));
87     LOS_ListDelete(&vnode->actFreeEntry);
88     g_freeVnodeSize--;
89     return vnode;
90 }
91 
VnodeReclaimLru(void)92 struct Vnode *VnodeReclaimLru(void)
93 {
94     struct Vnode *item = NULL;
95     struct Vnode *nextItem = NULL;
96     int releaseCount = 0;
97 
98     LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &g_vnodeActiveList, struct Vnode, actFreeEntry) {
99         if ((item->useCount > 0) ||
100             (item->flag & VNODE_FLAG_MOUNT_ORIGIN) ||
101             (item->flag & VNODE_FLAG_MOUNT_NEW)) {
102             continue;
103         }
104 
105         if (VnodeFree(item) == LOS_OK) {
106             releaseCount++;
107         }
108         if (releaseCount >= VNODE_LRU_COUNT) {
109             break;
110         }
111     }
112 
113     if (releaseCount == 0) {
114         PRINT_ERR("VnodeAlloc failed, vnode size hit max but can't reclaim anymore!\n");
115         return NULL;
116     }
117 
118     item = GetFromFreeList();
119     if (item == NULL) {
120         PRINT_ERR("VnodeAlloc failed, reclaim and get from free list failed!\n");
121     }
122     return item;
123 }
124 
VnodeAlloc(struct VnodeOps * vop,struct Vnode ** newVnode)125 int VnodeAlloc(struct VnodeOps *vop, struct Vnode **newVnode)
126 {
127     struct Vnode* vnode = NULL;
128 
129     VnodeHold();
130     vnode = GetFromFreeList();
131     if ((vnode == NULL) && g_totalVnodeSize < LOSCFG_MAX_VNODE_SIZE) {
132         vnode = (struct Vnode*)zalloc(sizeof(struct Vnode));
133         g_totalVnodeSize++;
134     }
135 
136     if (vnode == NULL) {
137         vnode = VnodeReclaimLru();
138     }
139 
140     if (vnode == NULL) {
141         *newVnode = NULL;
142         VnodeDrop();
143         return -ENOMEM;
144     }
145 
146     vnode->type = VNODE_TYPE_UNKNOWN;
147     LOS_ListInit((&(vnode->parentPathCaches)));
148     LOS_ListInit((&(vnode->childPathCaches)));
149     LOS_ListInit((&(vnode->hashEntry)));
150     LOS_ListInit((&(vnode->actFreeEntry)));
151 
152     if (vop == NULL) {
153         LOS_ListAdd(&g_vnodeVirtualList, &(vnode->actFreeEntry));
154         vnode->vop = &g_devfsOps;
155     } else {
156         LOS_ListTailInsert(&g_vnodeActiveList, &(vnode->actFreeEntry));
157         vnode->vop = vop;
158     }
159     LOS_ListInit(&vnode->mapping.page_list);
160     LOS_SpinInit(&vnode->mapping.list_lock);
161     (VOID)LOS_MuxInit(&vnode->mapping.mux_lock, NULL);
162     vnode->mapping.host = vnode;
163 
164     VnodeDrop();
165 
166     *newVnode = vnode;
167 
168     return LOS_OK;
169 }
170 
VnodeFree(struct Vnode * vnode)171 int VnodeFree(struct Vnode *vnode)
172 {
173     if (vnode == NULL) {
174         return LOS_OK;
175     }
176 
177     VnodeHold();
178     if (vnode->useCount > 0) {
179         VnodeDrop();
180         return -EBUSY;
181     }
182 
183     VnodePathCacheFree(vnode);
184     LOS_ListDelete(&(vnode->hashEntry));
185     LOS_ListDelete(&vnode->actFreeEntry);
186 
187     if (vnode->vop->Reclaim) {
188         vnode->vop->Reclaim(vnode);
189     }
190 
191     if (vnode->filePath) {
192         free(vnode->filePath);
193     }
194     if (vnode->vop == &g_devfsOps) {
195         /* for dev vnode, just free it */
196         free(vnode->data);
197         free(vnode);
198         g_totalVnodeSize--;
199     } else {
200         /* for normal vnode, reclaim it to g_VnodeFreeList */
201         (void)memset_s(vnode, sizeof(struct Vnode), 0, sizeof(struct Vnode));
202         LOS_ListAdd(&g_vnodeFreeList, &vnode->actFreeEntry);
203         g_freeVnodeSize++;
204     }
205     VnodeDrop();
206 
207     return LOS_OK;
208 }
209 
VnodeFreeAll(const struct Mount * mount)210 int VnodeFreeAll(const struct Mount *mount)
211 {
212     struct Vnode *vnode = NULL;
213     struct Vnode *nextVnode = NULL;
214     int ret;
215 
216     LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(vnode, nextVnode, &g_vnodeActiveList, struct Vnode, actFreeEntry) {
217         if ((vnode->originMount == mount) && !(vnode->flag & VNODE_FLAG_MOUNT_NEW)) {
218             ret = VnodeFree(vnode);
219             if (ret != LOS_OK) {
220                 return ret;
221             }
222         }
223     }
224 
225     return LOS_OK;
226 }
227 
VnodeInUseIter(const struct Mount * mount)228 BOOL VnodeInUseIter(const struct Mount *mount)
229 {
230     struct Vnode *vnode = NULL;
231 
232     LOS_DL_LIST_FOR_EACH_ENTRY(vnode, &g_vnodeActiveList, struct Vnode, actFreeEntry) {
233         if (vnode->originMount == mount) {
234             if ((vnode->useCount > 0) || (vnode->flag & VNODE_FLAG_MOUNT_ORIGIN)) {
235                 return TRUE;
236             }
237         }
238     }
239     return FALSE;
240 }
241 
VnodeHold(void)242 int VnodeHold(void)
243 {
244     int ret = LOS_MuxLock(&g_vnodeMux, LOS_WAIT_FOREVER);
245     if (ret != LOS_OK) {
246         PRINT_ERR("VnodeHold lock failed !\n");
247     }
248     return ret;
249 }
250 
VnodeDrop(void)251 int VnodeDrop(void)
252 {
253     int ret = LOS_MuxUnlock(&g_vnodeMux);
254     if (ret != LOS_OK) {
255         PRINT_ERR("VnodeDrop unlock failed !\n");
256     }
257     return ret;
258 }
259 
NextName(char * pos,uint8_t * len)260 static char *NextName(char *pos, uint8_t *len)
261 {
262     char *name = NULL;
263     while (*pos != 0 && *pos == '/') {
264         pos++;
265     }
266     if (*pos == '\0') {
267         return NULL;
268     }
269     name = (char *)pos;
270     while (*pos != '\0' && *pos != '/') {
271         pos++;
272     }
273     *len = pos - name;
274     return name;
275 }
276 
PreProcess(const char * originPath,struct Vnode ** startVnode,char ** path)277 static int PreProcess(const char *originPath, struct Vnode **startVnode, char **path)
278 {
279     int ret;
280     char *absolutePath = NULL;
281 
282     ret = vfs_normalize_path(NULL, originPath, &absolutePath);
283     if (ret == LOS_OK) {
284         *startVnode = g_rootVnode;
285         *path = absolutePath;
286     }
287 
288     return ret;
289 }
290 
ConvertVnodeIfMounted(struct Vnode * vnode)291 static struct Vnode *ConvertVnodeIfMounted(struct Vnode *vnode)
292 {
293     if ((vnode == NULL) || !(vnode->flag & VNODE_FLAG_MOUNT_ORIGIN)) {
294         return vnode;
295     }
296     return vnode->newMount->vnodeCovered;
297 }
298 
RefreshLRU(struct Vnode * vnode)299 static void RefreshLRU(struct Vnode *vnode)
300 {
301     if (vnode == NULL || (vnode->type != VNODE_TYPE_REG && vnode->type != VNODE_TYPE_DIR) ||
302         vnode->vop == &g_devfsOps || vnode->vop == NULL) {
303         return;
304     }
305     LOS_ListDelete(&(vnode->actFreeEntry));
306     LOS_ListTailInsert(&g_vnodeActiveList, &(vnode->actFreeEntry));
307 }
308 
ProcessVirtualVnode(struct Vnode * parent,uint32_t flags,struct Vnode ** vnode)309 static int ProcessVirtualVnode(struct Vnode *parent, uint32_t flags, struct Vnode **vnode)
310 {
311     int ret = -ENOENT;
312     if (flags & V_CREATE) {
313         // only create /dev/ vnode
314         ret = VnodeAlloc(NULL, vnode);
315     }
316     if (ret == LOS_OK) {
317         (*vnode)->parent = parent;
318     }
319     return ret;
320 }
321 
Step(char ** currentDir,struct Vnode ** currentVnode,uint32_t flags)322 static int Step(char **currentDir, struct Vnode **currentVnode, uint32_t flags)
323 {
324     int ret;
325     uint8_t len = 0;
326     struct Vnode *nextVnode = NULL;
327     char *nextDir = NULL;
328 
329     if ((*currentVnode)->type != VNODE_TYPE_DIR) {
330         return -ENOTDIR;
331     }
332     nextDir = NextName(*currentDir, &len);
333     if (nextDir == NULL) {
334         // there is '/' at the end of the *currentDir.
335         *currentDir = NULL;
336         return LOS_OK;
337     }
338 
339     ret = PathCacheLookup(*currentVnode, nextDir, len, &nextVnode);
340     if (ret == LOS_OK) {
341         goto STEP_FINISH;
342     }
343 
344     (*currentVnode)->useCount++;
345     if (flags & V_DUMMY) {
346         ret = ProcessVirtualVnode(*currentVnode, flags, &nextVnode);
347     } else {
348         if ((*currentVnode)->vop != NULL && (*currentVnode)->vop->Lookup != NULL) {
349             ret = (*currentVnode)->vop->Lookup(*currentVnode, nextDir, len, &nextVnode);
350         } else {
351             ret = -ENOSYS;
352         }
353     }
354     (*currentVnode)->useCount--;
355 
356     if (ret == LOS_OK) {
357         (void)PathCacheAlloc((*currentVnode), nextVnode, nextDir, len);
358     }
359 
360 STEP_FINISH:
361     nextVnode = ConvertVnodeIfMounted(nextVnode);
362     RefreshLRU(nextVnode);
363 
364     *currentDir = nextDir + len;
365     if (ret == LOS_OK) {
366         *currentVnode = nextVnode;
367     }
368 
369     return ret;
370 }
371 
VnodeLookupAt(const char * path,struct Vnode ** result,uint32_t flags,struct Vnode * orgVnode)372 int VnodeLookupAt(const char *path, struct Vnode **result, uint32_t flags, struct Vnode *orgVnode)
373 {
374     int ret;
375     int vnodePathLen;
376     char *vnodePath = NULL;
377     struct Vnode *startVnode = NULL;
378     char *normalizedPath = NULL;
379 
380     if (orgVnode != NULL) {
381         startVnode = orgVnode;
382         normalizedPath = strdup(path);
383         if (normalizedPath == NULL) {
384             PRINT_ERR("[VFS]lookup failed, strdup err\n");
385             ret = -EINVAL;
386             goto OUT_FREE_PATH;
387         }
388     } else {
389         ret = PreProcess(path, &startVnode, &normalizedPath);
390         if (ret != LOS_OK) {
391             PRINT_ERR("[VFS]lookup failed, invalid path err = %d\n", ret);
392             goto OUT_FREE_PATH;
393         }
394     }
395 
396     if (normalizedPath[1] == '\0' && normalizedPath[0] == '/') {
397         *result = g_rootVnode;
398         free(normalizedPath);
399         return LOS_OK;
400     }
401 
402     char *currentDir = normalizedPath;
403     struct Vnode *currentVnode = startVnode;
404 
405     while (*currentDir != '\0') {
406         ret = Step(&currentDir, &currentVnode, flags);
407         if (currentDir == NULL || *currentDir == '\0') {
408             // return target or parent vnode as result
409             *result = currentVnode;
410             if (currentVnode->filePath == NULL) {
411                 currentVnode->filePath = normalizedPath;
412             } else {
413                 free(normalizedPath);
414             }
415             return ret;
416         } else if (VfsVnodePermissionCheck(currentVnode, EXEC_OP)) {
417             ret = -EACCES;
418             goto OUT_FREE_PATH;
419         }
420 
421         if (ret != LOS_OK) {
422             // no such file, lookup failed
423             goto OUT_FREE_PATH;
424         }
425         if (currentVnode->filePath == NULL) {
426             vnodePathLen = currentDir - normalizedPath;
427             vnodePath = malloc(vnodePathLen + 1);
428             if (vnodePath == NULL) {
429                 ret = -ENOMEM;
430                 goto OUT_FREE_PATH;
431             }
432             ret = strncpy_s(vnodePath, vnodePathLen + 1, normalizedPath, vnodePathLen);
433             if (ret != EOK) {
434                 ret = -ENAMETOOLONG;
435                 free(vnodePath);
436                 goto OUT_FREE_PATH;
437             }
438             currentVnode->filePath = vnodePath;
439             currentVnode->filePath[vnodePathLen] = 0;
440         }
441     }
442 
443 OUT_FREE_PATH:
444     if (normalizedPath) {
445         free(normalizedPath);
446     }
447     return ret;
448 }
449 
VnodeLookup(const char * path,struct Vnode ** vnode,uint32_t flags)450 int VnodeLookup(const char *path, struct Vnode **vnode, uint32_t flags)
451 {
452     return VnodeLookupAt(path, vnode, flags, NULL);
453 }
454 
VnodeLookupFullpath(const char * fullpath,struct Vnode ** vnode,uint32_t flags)455 int VnodeLookupFullpath(const char *fullpath, struct Vnode **vnode, uint32_t flags)
456 {
457     return VnodeLookupAt(fullpath, vnode, flags, g_rootVnode);
458 }
459 
ChangeRootInternal(struct Vnode * rootOld,char * dirname)460 static void ChangeRootInternal(struct Vnode *rootOld, char *dirname)
461 {
462     int ret;
463     struct Mount *mnt = NULL;
464     char *name = NULL;
465     struct Vnode *node = NULL;
466     struct Vnode *nodeInFs = NULL;
467     struct PathCache *item = NULL;
468     struct PathCache *nextItem = NULL;
469 
470     LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &rootOld->childPathCaches, struct PathCache, childEntry) {
471         name = item->name;
472         node = item->childVnode;
473 
474         if (strcmp(name, dirname)) {
475             continue;
476         }
477         PathCacheFree(item);
478 
479         ret = VnodeLookup(dirname, &nodeInFs, 0);
480         if (ret) {
481             PRINTK("%s-%d %s NOT exist in rootfs\n", __FUNCTION__, __LINE__, dirname);
482             break;
483         }
484 
485         mnt = node->newMount;
486         mnt->vnodeBeCovered = nodeInFs;
487 
488         nodeInFs->newMount = mnt;
489         nodeInFs->flag |= VNODE_FLAG_MOUNT_ORIGIN;
490 
491         break;
492     }
493 }
494 
ChangeRoot(struct Vnode * rootNew)495 void ChangeRoot(struct Vnode *rootNew)
496 {
497     struct Vnode *rootOld = g_rootVnode;
498     g_rootVnode = rootNew;
499     ChangeRootInternal(rootOld, "proc");
500     ChangeRootInternal(rootOld, "dev");
501 }
502 
VnodeReaddir(struct Vnode * vp,struct fs_dirent_s * dir)503 static int VnodeReaddir(struct Vnode *vp, struct fs_dirent_s *dir)
504 {
505     int result;
506     int cnt = 0;
507     off_t i = 0;
508     off_t idx;
509     unsigned int dstNameSize;
510 
511     struct PathCache *item = NULL;
512     struct PathCache *nextItem = NULL;
513 
514     if (dir == NULL) {
515         return -EINVAL;
516     }
517 
518     LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &vp->childPathCaches, struct PathCache, childEntry) {
519         if (i < dir->fd_position) {
520             i++;
521             continue;
522         }
523 
524         idx = i - dir->fd_position;
525 
526         dstNameSize = sizeof(dir->fd_dir[idx].d_name);
527         result = strncpy_s(dir->fd_dir[idx].d_name, dstNameSize, item->name, item->nameLen);
528         if (result != EOK) {
529             return -ENAMETOOLONG;
530         }
531         dir->fd_dir[idx].d_off = i;
532         dir->fd_dir[idx].d_reclen = (uint16_t)sizeof(struct dirent);
533 
534         i++;
535         if (++cnt >= dir->read_cnt) {
536             break;
537         }
538     }
539 
540     dir->fd_position = i;
541 
542     return cnt;
543 }
544 
VnodeOpendir(struct Vnode * vnode,struct fs_dirent_s * dir)545 int VnodeOpendir(struct Vnode *vnode, struct fs_dirent_s *dir)
546 {
547     (void)vnode;
548     (void)dir;
549     return LOS_OK;
550 }
551 
VnodeClosedir(struct Vnode * vnode,struct fs_dirent_s * dir)552 int VnodeClosedir(struct Vnode *vnode, struct fs_dirent_s *dir)
553 {
554     (void)vnode;
555     (void)dir;
556     return LOS_OK;
557 }
558 
VnodeCreate(struct Vnode * parent,const char * name,int mode,struct Vnode ** vnode)559 int VnodeCreate(struct Vnode *parent, const char *name, int mode, struct Vnode **vnode)
560 {
561     int ret;
562     struct Vnode *newVnode = NULL;
563 
564     ret = VnodeAlloc(NULL, &newVnode);
565     if (ret != 0) {
566         return -ENOMEM;
567     }
568 
569     newVnode->type = VNODE_TYPE_CHR;
570     newVnode->vop = parent->vop;
571     newVnode->fop = parent->fop;
572     newVnode->data = NULL;
573     newVnode->parent = parent;
574     newVnode->originMount = parent->originMount;
575     newVnode->uid = parent->uid;
576     newVnode->gid = parent->gid;
577     newVnode->mode = mode;
578     /* The 'name' here is not full path, but for device we don't depend on this path, it's just a name for DFx.
579        When we have devfs, we can get a fullpath. */
580     newVnode->filePath = strdup(name);
581 
582     *vnode = newVnode;
583     return 0;
584 }
585 
VnodeDevInit(void)586 int VnodeDevInit(void)
587 {
588     struct Vnode *devNode = NULL;
589     struct Mount *devMount = NULL;
590 
591     int retval = VnodeLookup("/dev", &devNode, V_CREATE | V_DUMMY);
592     if (retval != LOS_OK) {
593         PRINT_ERR("VnodeDevInit failed error %d\n", retval);
594         return retval;
595     }
596     devNode->mode = DEV_VNODE_MODE | S_IFDIR;
597     devNode->type = VNODE_TYPE_DIR;
598 
599     devMount = MountAlloc(devNode, NULL);
600     if (devMount == NULL) {
601         PRINT_ERR("VnodeDevInit failed mount point alloc failed.\n");
602         return -ENOMEM;
603     }
604     devMount->vnodeCovered = devNode;
605     devMount->vnodeBeCovered->flag |= VNODE_FLAG_MOUNT_ORIGIN;
606     return LOS_OK;
607 }
608 
VnodeGetattr(struct Vnode * vnode,struct stat * buf)609 int VnodeGetattr(struct Vnode *vnode, struct stat *buf)
610 {
611     (void)memset_s(buf, sizeof(struct stat), 0, sizeof(struct stat));
612     buf->st_mode = vnode->mode;
613     buf->st_uid = vnode->uid;
614     buf->st_gid = vnode->gid;
615 
616     return LOS_OK;
617 }
618 
VnodeGetRoot(void)619 struct Vnode *VnodeGetRoot(void)
620 {
621     return g_rootVnode;
622 }
623 
VnodeChattr(struct Vnode * vnode,struct IATTR * attr)624 static int VnodeChattr(struct Vnode *vnode, struct IATTR *attr)
625 {
626     mode_t tmpMode;
627     if (vnode == NULL || attr == NULL) {
628         return -EINVAL;
629     }
630     if (attr->attr_chg_valid & CHG_MODE) {
631         tmpMode = attr->attr_chg_mode;
632         tmpMode &= ~S_IFMT;
633         vnode->mode &= S_IFMT;
634         vnode->mode = tmpMode | vnode->mode;
635     }
636     if (attr->attr_chg_valid & CHG_UID) {
637         vnode->uid = attr->attr_chg_uid;
638     }
639     if (attr->attr_chg_valid & CHG_GID) {
640         vnode->gid = attr->attr_chg_gid;
641     }
642     return LOS_OK;
643 }
644 
VnodeDevLookup(struct Vnode * parentVnode,const char * path,int len,struct Vnode ** vnode)645 int VnodeDevLookup(struct Vnode *parentVnode, const char *path, int len, struct Vnode **vnode)
646 {
647     (void)parentVnode;
648     (void)path;
649     (void)len;
650     (void)vnode;
651     /* dev node must in pathCache. */
652     return -ENOENT;
653 }
654 
655 static struct VnodeOps g_devfsOps = {
656     .Lookup = VnodeDevLookup,
657     .Getattr = VnodeGetattr,
658     .Readdir = VnodeReaddir,
659     .Opendir = VnodeOpendir,
660     .Closedir = VnodeClosedir,
661     .Create = VnodeCreate,
662     .Chattr = VnodeChattr,
663 };
664 
VnodeMemoryDump(void)665 void VnodeMemoryDump(void)
666 {
667     struct Vnode *item = NULL;
668     struct Vnode *nextItem = NULL;
669     int vnodeCount = 0;
670 
671     LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &g_vnodeActiveList, struct Vnode, actFreeEntry) {
672         if ((item->useCount > 0) ||
673             (item->flag & VNODE_FLAG_MOUNT_ORIGIN) ||
674             (item->flag & VNODE_FLAG_MOUNT_NEW)) {
675             continue;
676         }
677 
678         vnodeCount++;
679     }
680 
681     PRINTK("Vnode number = %d\n", vnodeCount);
682     PRINTK("Vnode memory size = %d(B)\n", vnodeCount * sizeof(struct Vnode));
683 }
684 
GetVnodeFreeList()685 LIST_HEAD* GetVnodeFreeList()
686 {
687     return &g_vnodeFreeList;
688 }
689 
GetVnodeVirtualList()690 LIST_HEAD* GetVnodeVirtualList()
691 {
692     return &g_vnodeVirtualList;
693 }
694 
GetVnodeActiveList()695 LIST_HEAD* GetVnodeActiveList()
696 {
697     return &g_vnodeActiveList;
698 }
699 
VnodeClearCache(void)700 int VnodeClearCache(void)
701 {
702     struct Vnode *item = NULL;
703     struct Vnode *nextItem = NULL;
704     int count = 0;
705 
706     VnodeHold();
707     LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &g_vnodeActiveList, struct Vnode, actFreeEntry) {
708         if ((item->useCount > 0) ||
709             (item->flag & VNODE_FLAG_MOUNT_ORIGIN) ||
710             (item->flag & VNODE_FLAG_MOUNT_NEW)) {
711             continue;
712         }
713 
714         if (VnodeFree(item) == LOS_OK) {
715             count++;
716         }
717     }
718     VnodeDrop();
719 
720     return count;
721 }
722