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 38LIST_HEAD g_vnodeFreeList; /* free vnodes list */ 39LIST_HEAD g_vnodeVirtualList; /* dev vnodes list */ 40LIST_HEAD g_vnodeActiveList; /* inuse vnodes list */ 41static int g_freeVnodeSize = 0; /* system free vnodes size */ 42static int g_totalVnodeSize = 0; /* total vnode size */ 43 44static LosMux g_vnodeMux; 45static struct Vnode *g_rootVnode = NULL; 46static 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 52int 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 82static 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 101struct 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 134int 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 180int 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 219int 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 237BOOL 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 251int 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 260int 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 269static 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 286static 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 300static 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 322static 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 332static 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 345static 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 383STEP_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 395int 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 466OUT_FREE_PATH: 467 if (normalizedPath) { 468 free(normalizedPath); 469 } 470 return ret; 471} 472 473int VnodeLookup(const char *path, struct Vnode **vnode, uint32_t flags) 474{ 475 return VnodeLookupAt(path, vnode, flags, NULL); 476} 477 478int VnodeLookupFullpath(const char *fullpath, struct Vnode **vnode, uint32_t flags) 479{ 480 return VnodeLookupAt(fullpath, vnode, flags, GetCurrRootVnode()); 481} 482 483static 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 518void 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 537static 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 579int VnodeOpendir(struct Vnode *vnode, struct fs_dirent_s *dir) 580{ 581 (void)vnode; 582 (void)dir; 583 return LOS_OK; 584} 585 586int VnodeClosedir(struct Vnode *vnode, struct fs_dirent_s *dir) 587{ 588 (void)vnode; 589 (void)dir; 590 return LOS_OK; 591} 592 593int 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 620int 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 643int 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 653struct Vnode *VnodeGetRoot(void) 654{ 655 return g_rootVnode; 656} 657 658static 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 679int 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 689static 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 699void 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 720struct 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 740LIST_HEAD* GetVnodeFreeList() 741{ 742 return &g_vnodeFreeList; 743} 744 745LIST_HEAD* GetVnodeVirtualList() 746{ 747 return &g_vnodeVirtualList; 748} 749 750LIST_HEAD* GetVnodeActiveList() 751{ 752 return &g_vnodeActiveList; 753} 754 755int 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 778struct 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