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(¤tDir, ¤tVnode, 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