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