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