更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
vnode.c
浏览该文件的文档.
1/*
2 * Copyright (c) 2021-2021 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/**
37 * @brief
38 * @ver
39 */
40
41LIST_HEAD g_vnodeFreeList; /* free vnodes list | 空闲节点链表*/
42LIST_HEAD g_vnodeVirtualList; /* dev vnodes list | 虚拟设备节点链表,暂无实际的文件系统*/
43LIST_HEAD g_vnodeActiveList; /* inuse vnodes list | 正在使用的虚拟节点链表*/
44static int g_freeVnodeSize = 0; /* system free vnodes size | 剩余节点数量*/
45static int g_totalVnodeSize = 0; /* total vnode size | 已分配的总节点数量*/
46
47static LosMux g_vnodeMux; ///< 操作链表互斥量
48static struct Vnode *g_rootVnode = NULL;///< 根节点
49static struct VnodeOps g_devfsOps; ///< 设备文件节点操作
50/*********************************************************
51linux下有专门的文件系统(devfs | sysfs)用来对设备进行管理,鸿蒙目前只支持 devfs方式
52devfs和sysfs都是和proc一样,是一个虚拟的文件系统,提供了一种类似于文件的方法来管理位于/dev目录下的所有设备,
53/dev目录下的每一个文件都对应的是一个设备,至于当前该设备存在与否不重要,先把坑位占了.
54
55devfs:设备文件系统
56提供类似于文件的方法来管理位于/dev目录下的设备
571.根目录/dev
58 设备文件创建
59 创建根文件系统时创建基本的,比如console,tty*等等
60 设备驱动加载时创建相应的设备文件
612.特殊设备文件
62 /dev/console
63 /dev/null /dev/zero :黑洞文件
643.缺点
65 不确定的设备映射,有时一个设备映射的设备文件可能不同,假如挂载的u盘可能对应sda也可能对应sdb
66 没有足够的主/辅设备号,当设备过多的时候,显然会成为一个问题
67**********************************************************/
68
69#define ENTRY_TO_VNODE(ptr) LOS_DL_LIST_ENTRY(ptr, struct Vnode, actFreeEntry) ///< 通过局部(actFreeEntry)找到整体(Vnode)
70#define VNODE_LRU_COUNT 10 ///< 最多回收数量
71#define DEV_VNODE_MODE 0755 ///< 0755可不是深圳的意思哈,而是节点的权限,对照以下注释理解
72/*!
73#ifndef S_IRUSR
74#define S_ISUID 04000
75#define S_ISGID 02000
76#define S_ISVTX 01000
77#define S_IRUSR 0400
78#define S_IWUSR 0200
79#define S_IXUSR 0100
80#define S_IRWXU 0700
81#define S_IRGRP 0040
82#define S_IWGRP 0020
83#define S_IXGRP 0010
84#define S_IRWXG 0070
85#define S_IROTH 0004
86#define S_IWOTH 0002
87#define S_IXOTH 0001
88#define S_IRWXO 0007
89#endif
90*/
91int VnodesInit(void)
92{
93 int retval = LOS_MuxInit(&g_vnodeMux, NULL);//初始化操作vnode链表的互斥量
94 if (retval != LOS_OK) {
95 PRINT_ERR("Create mutex for vnode fail, status: %d", retval);
96 return retval;
97 }
98
99 LOS_ListInit(&g_vnodeFreeList); //初始化空闲的节点链表
100 LOS_ListInit(&g_vnodeVirtualList); //初始化虚拟节点链表
101 LOS_ListInit(&g_vnodeActiveList); //初始化活动虚拟节点链表
102 retval = VnodeAlloc(NULL, &g_rootVnode);//分配根节点
103 if (retval != LOS_OK) {
104 PRINT_ERR("VnodeInit failed error %d\n", retval);
105 return retval;
106 }
107 g_rootVnode->mode = S_IRWXU | S_IRWXG | S_IRWXO | S_IFDIR;// 40777 (chmod 777)
108 g_rootVnode->type = VNODE_TYPE_DIR;//节点类型为目录
109 g_rootVnode->filePath = "/";
110
111 return LOS_OK;
112}
113///获取空闲节点链表,分配的节点从空闲链表里出
114static struct Vnode *GetFromFreeList(void)
115{
116 if (g_freeVnodeSize <= 0) {
117 return NULL;
118 }
119 struct Vnode *vnode = NULL;
120
122 PRINT_ERR("get vnode from free list failed, list empty but g_freeVnodeSize = %d!\n", g_freeVnodeSize);
123 g_freeVnodeSize = 0;
124 return NULL;
125 }
126
127 vnode = ENTRY_TO_VNODE(LOS_DL_LIST_FIRST(&g_vnodeFreeList));
128 LOS_ListDelete(&vnode->actFreeEntry);//从空闲链表上摘出去.
130 return vnode;
131}
132///节点批量回收, LRU是Least Recently Used的缩写,即最近最少使用,
134{
135 struct Vnode *item = NULL;
136 struct Vnode *nextItem = NULL;
137 int releaseCount = 0;
138 //遍历链表
139 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &g_vnodeActiveList, struct Vnode, actFreeEntry) {
140 if ((item->useCount > 0) || //还有链接数
141 (item->flag & VNODE_FLAG_MOUNT_ORIGIN) || //原来是个mount节点
142 (item->flag & VNODE_FLAG_MOUNT_NEW)) { //是个新mount节点
143 continue;
144 }
145
146 if (VnodeFree(item) == LOS_OK) {//正式回收,其实就是将自己从链表上摘出去,再挂到空闲链表上.
147 releaseCount++;
148 }
149 if (releaseCount >= VNODE_LRU_COUNT) {//一次最多回收量
150 break;
151 }
152 }
153
154 if (releaseCount == 0) {//回收失败
155 PRINT_ERR("VnodeAlloc failed, vnode size hit max but can't reclaim anymore!\n");
156 return NULL;
157 }
158
159 item = GetFromFreeList();//获取一个空闲节点
160 if (item == NULL) {
161 PRINT_ERR("VnodeAlloc failed, reclaim and get from free list failed!\n");
162 }
163 return item;
164}
165///申请分配一个 vnode 节点,vop为操作节点的驱动程序
166int VnodeAlloc(struct VnodeOps *vop, struct Vnode **newVnode)
167{
168 struct Vnode* vnode = NULL;
169
170 VnodeHold();
171 vnode = GetFromFreeList();
172 if ((vnode == NULL) && g_totalVnodeSize < LOSCFG_MAX_VNODE_SIZE) {
173 vnode = (struct Vnode*)zalloc(sizeof(struct Vnode));
175 }
176
177 if (vnode == NULL) {//没有分配到节点
178 vnode = VnodeReclaimLru();//执行回收算法,释放节点
179 }
180
181 if (vnode == NULL) {//回收也没有可用节点
182 *newVnode = NULL;
183 VnodeDrop();
184 return -ENOMEM;//分配失败,返回
185 }
186
187 vnode->type = VNODE_TYPE_UNKNOWN; //节点默认类型,未知
188 LOS_ListInit((&(vnode->parentPathCaches)));//后续可能要当爸爸,做好准备
189 LOS_ListInit((&(vnode->childPathCaches)));//后续可能要当儿子,做好准备
190 LOS_ListInit((&(vnode->hashEntry))); //用它挂到全局哈希表上
191 LOS_ListInit((&(vnode->actFreeEntry))); //用它挂到全局正使用节点链表上
192
193 if (vop == NULL) {//
194 LOS_ListAdd(&g_vnodeVirtualList, &(vnode->actFreeEntry));//挂到虚拟设备
195 vnode->vop = &g_devfsOps;
196 } else {//如果已有指定的文件系统(FAT),直接绑定
198 vnode->vop = vop;
199 }
202 (VOID)LOS_MuxInit(&vnode->mapping.mux_lock, NULL);
203 vnode->mapping.host = vnode;
204
205 VnodeDrop();
206
207 *newVnode = vnode;
208
209 return LOS_OK;
210}
211///是否 vnode 节点
212int VnodeFree(struct Vnode *vnode)
213{
214 if (vnode == NULL) {
215 return LOS_OK;
216 }
217
218 VnodeHold();//拿互斥锁
219 if (vnode->useCount > 0) {//还有引用数,或者叫链接数.这里的链接数指的是还有硬链接没删除的情况
220 VnodeDrop();
221 return -EBUSY;//返回设备或资源忙着呢.
222 }
223
224 VnodePathCacheFree(vnode);//节点和父亲,孩子告别
225 LOS_ListDelete(&(vnode->hashEntry));//将自己从当前哈希链表上摘出来,此时vnode通过hashEntry挂在 g_vnodeHashEntrys
226 LOS_ListDelete(&vnode->actFreeEntry);//将自己从当前链表摘出来,此时vnode通过actFreeEntry挂在 g_vnodeCurrList
227
228 if (vnode->vop->Reclaim) {//资源的回收操作
229 vnode->vop->Reclaim(vnode);//先回收资源
230 }
231
232 if (vnode->filePath) {
233 free(vnode->filePath);
234 }
235 if (vnode->vop == &g_devfsOps) {//对设备文件的回收
236 /* for dev vnode, just free it */
237 free(vnode->data);//
238 free(vnode);
240 } else {
241 /* for normal vnode, reclaim it to g_VnodeFreeList */
242 (void)memset_s(vnode, sizeof(struct Vnode), 0, sizeof(struct Vnode));
243 LOS_ListAdd(&g_vnodeFreeList, &vnode->actFreeEntry);//actFreeEntry换个地方挂,从活动链接换到空闲链表上.
244 g_freeVnodeSize++;//空闲链表节点数量增加
245 }
246 VnodeDrop();//释放互斥锁
247
248 return LOS_OK;
249}
250///释放mount下所有的索引节点
251int VnodeFreeAll(const struct Mount *mount)
252{
253 struct Vnode *vnode = NULL;
254 struct Vnode *nextVnode = NULL;
255 int ret;
256
257 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(vnode, nextVnode, &g_vnodeActiveList, struct Vnode, actFreeEntry) {
258 if ((vnode->originMount == mount) && !(vnode->flag & VNODE_FLAG_MOUNT_NEW)) {//找到装载点,且这个装载点没有被新使用
259 ret = VnodeFree(vnode);//释放节点,@note_thinking 是不是树杈被释放后,树叶也默认被释放了?
260 if (ret != LOS_OK) {
261 return ret;
262 }
263 }
264 }
265
266 return LOS_OK;
267}
268///mount是否正在被某个索引节点使用
269BOOL VnodeInUseIter(const struct Mount *mount)
270{
271 struct Vnode *vnode = NULL;
272
273 LOS_DL_LIST_FOR_EACH_ENTRY(vnode, &g_vnodeActiveList, struct Vnode, actFreeEntry) {//遍历活动链表
274 if (vnode->originMount == mount) {//找到一致挂载点
275 if ((vnode->useCount > 0) || (vnode->flag & VNODE_FLAG_MOUNT_ORIGIN)) {//还在被使用
276 return TRUE;
277 }
278 }
279 }
280 return FALSE;
281}
282///拿锁,封装互斥量
284{
285 int ret = LOS_MuxLock(&g_vnodeMux, LOS_WAIT_FOREVER);
286 if (ret != LOS_OK) {
287 PRINT_ERR("VnodeHold lock failed !\n");
288 }
289 return ret;
290}
291///归还锁
293{
294 int ret = LOS_MuxUnlock(&g_vnodeMux);
295 if (ret != LOS_OK) {
296 PRINT_ERR("VnodeDrop unlock failed !\n");
297 }
298 return ret;
299}
300///
301static char *NextName(char *pos, uint8_t *len)
302{
303 char *name = NULL;
304 while (*pos != 0 && *pos == '/') {
305 pos++;
306 }
307 if (*pos == '\0') {
308 return NULL;
309 }
310 name = (char *)pos;
311 while (*pos != '\0' && *pos != '/') {
312 pos++;
313 }
314 *len = pos - name;
315 return name;
316}
317///处理前的准备
318static int PreProcess(const char *originPath, struct Vnode **startVnode, char **path)
319{
320 int ret;
321 char *absolutePath = NULL;
322 //通过相对路径找到绝对路径
323 ret = vfs_normalize_path(NULL, originPath, &absolutePath);
324 if (ret == LOS_OK) {//成功
325 *startVnode = g_rootVnode;//根节点为开始节点
326 *path = absolutePath;//返回绝对路径
327 }
328
329 return ret;
330}
331
332static struct Vnode *ConvertVnodeIfMounted(struct Vnode *vnode)
333{
334 if ((vnode == NULL) || !(vnode->flag & VNODE_FLAG_MOUNT_ORIGIN)) {
335 return vnode;
336 }
337 return vnode->newMount->vnodeCovered;
338}
339///刷新虚拟节点
340static void RefreshLRU(struct Vnode *vnode)
341{
342 if (vnode == NULL || (vnode->type != VNODE_TYPE_REG && vnode->type != VNODE_TYPE_DIR) ||
343 vnode->vop == &g_devfsOps || vnode->vop == NULL) {
344 return;
345 }
346 LOS_ListDelete(&(vnode->actFreeEntry));
348}
349
350static int ProcessVirtualVnode(struct Vnode *parent, uint32_t flags, struct Vnode **vnode)
351{
352 int ret = -ENOENT;
353 if (flags & V_CREATE) {
354 // only create /dev/ vnode
355 ret = VnodeAlloc(NULL, vnode);
356 }
357 if (ret == LOS_OK) {
358 (*vnode)->parent = parent;
359 }
360 return ret;
361}
362///一级一级向下找
363static int Step(char **currentDir, struct Vnode **currentVnode, uint32_t flags)
364{
365 int ret;
366 uint8_t len = 0;
367 struct Vnode *nextVnode = NULL;
368 char *nextDir = NULL;
369
370 if ((*currentVnode)->type != VNODE_TYPE_DIR) {//必须是目录节点
371 return -ENOTDIR;
372 }
373 nextDir = NextName(*currentDir, &len);//
374 if (nextDir == NULL) {
375 *currentDir = NULL;
376 return LOS_OK;
377 }
378
379 ret = PathCacheLookup(*currentVnode, nextDir, len, &nextVnode);
380 if (ret == LOS_OK) {
381 goto STEP_FINISH;
382 }
383
384 (*currentVnode)->useCount++;
385 if (flags & V_DUMMY) {
386 ret = ProcessVirtualVnode(*currentVnode, flags, &nextVnode);
387 } else {
388 if ((*currentVnode)->vop != NULL && (*currentVnode)->vop->Lookup != NULL) {
389 ret = (*currentVnode)->vop->Lookup(*currentVnode, nextDir, len, &nextVnode);
390 } else {
391 ret = -ENOSYS;
392 }
393 }
394 (*currentVnode)->useCount--;
395
396 if (ret == LOS_OK) {
397 (void)PathCacheAlloc((*currentVnode), nextVnode, nextDir, len);
398 }
399
400STEP_FINISH:
401 nextVnode = ConvertVnodeIfMounted(nextVnode);
402 RefreshLRU(nextVnode);
403
404 *currentDir = nextDir + len;
405 if (ret == LOS_OK) {
406 *currentVnode = nextVnode;
407 }
408
409 return ret;
410}
411///通过路径 查找索引节点.路径和节点是 N:1的关系, 硬链接
412int VnodeLookupAt(const char *path, struct Vnode **result, uint32_t flags, struct Vnode *orgVnode)
413{
414 int ret;
415 int vnodePathLen;
416 char *vnodePath = NULL;
417 struct Vnode *startVnode = NULL;
418 char *normalizedPath = NULL;
419
420 if (orgVnode != NULL) {
421 startVnode = orgVnode;
422 normalizedPath = strdup(path);
423 if (normalizedPath == NULL) {
424 PRINT_ERR("[VFS]lookup failed, strdup err\n");
425 ret = -EINVAL;
426 goto OUT_FREE_PATH;
427 }
428 } else {
429 ret = PreProcess(path, &startVnode, &normalizedPath);
430 if (ret != LOS_OK) {
431 PRINT_ERR("[VFS]lookup failed, invalid path err = %d\n", ret);
432 goto OUT_FREE_PATH;
433 }
434 }
435
436 if (normalizedPath[1] == '\0' && normalizedPath[0] == '/') {
437 *result = g_rootVnode;//啥也不说了,还找啥呀,直接返回根节点
438 free(normalizedPath);
439 return LOS_OK;
440 }
441
442 char *currentDir = normalizedPath;
443 struct Vnode *currentVnode = startVnode;
444
445 while (*currentDir != '\0') {
446 ret = Step(&currentDir, &currentVnode, flags);
447 if (currentDir == NULL || *currentDir == '\0') {
448 // return target or parent vnode as result
449 *result = currentVnode;
450 if (currentVnode->filePath == NULL) {
451 currentVnode->filePath = normalizedPath;
452 } else {
453 free(normalizedPath);
454 }
455 return ret;
456 } else if (VfsVnodePermissionCheck(currentVnode, EXEC_OP)) {
457 ret = -EACCES;
458 goto OUT_FREE_PATH;
459 }
460
461 if (ret != LOS_OK) {
462 // no such file, lookup failed
463 goto OUT_FREE_PATH;
464 }
465 if (currentVnode->filePath == NULL) {
466 vnodePathLen = currentDir - normalizedPath;
467 vnodePath = malloc(vnodePathLen + 1);
468 if (vnodePath == NULL) {
469 ret = -ENOMEM;
470 goto OUT_FREE_PATH;
471 }
472 ret = strncpy_s(vnodePath, vnodePathLen + 1, normalizedPath, vnodePathLen);
473 if (ret != EOK) {
474 ret = -ENAMETOOLONG;
475 free(vnodePath);
476 goto OUT_FREE_PATH;
477 }
478 currentVnode->filePath = vnodePath;
479 currentVnode->filePath[vnodePathLen] = 0;
480 }
481 }
482
483OUT_FREE_PATH:
484 if (normalizedPath) {
485 free(normalizedPath);
486 }
487
488 return ret;
489}
490///通过路径查询vnode节点
491int VnodeLookup(const char *path, struct Vnode **vnode, uint32_t flags)
492{
493 return VnodeLookupAt(path, vnode, flags, NULL);
494}
495///根节点内部改变
496int VnodeLookupFullpath(const char *fullpath, struct Vnode **vnode, uint32_t flags)
497{
498 return VnodeLookupAt(fullpath, vnode, flags, g_rootVnode);
499}
500
501static void ChangeRootInternal(struct Vnode *rootOld, char *dirname)
502{
503 int ret;
504 struct Mount *mnt = NULL;
505 char *name = NULL;
506 struct Vnode *node = NULL;
507 struct Vnode *nodeInFs = NULL;
508 struct PathCache *item = NULL;
509 struct PathCache *nextItem = NULL;
510 //遍历参数节点孩子节点
511 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &rootOld->childPathCaches, struct PathCache, childEntry) {
512 name = item->name;
513 node = item->childVnode;
514
515 if (strcmp(name, dirname)) {
516 continue;
517 }
518 PathCacheFree(item);
519
520 ret = VnodeLookup(dirname, &nodeInFs, 0);
521 if (ret) {
522 PRINTK("%s-%d %s NOT exist in rootfs\n", __FUNCTION__, __LINE__, dirname);
523 break;
524 }
525
526 mnt = node->newMount;
527 mnt->vnodeBeCovered = nodeInFs;
528
529 nodeInFs->newMount = mnt;
530 nodeInFs->flag |= VNODE_FLAG_MOUNT_ORIGIN;
531
532 break;
533 }
534}
535///改变根节点
536void ChangeRoot(struct Vnode *rootNew)
537{
538 struct Vnode *rootOld = g_rootVnode;
539 g_rootVnode = rootNew;
540 ChangeRootInternal(rootOld, "proc");
541 ChangeRootInternal(rootOld, "dev");
542}
543
544static int VnodeReaddir(struct Vnode *vp, struct fs_dirent_s *dir)
545{
546 int result;
547 int cnt = 0;
548 off_t i = 0;
549 off_t idx;
550 unsigned int dstNameSize;
551
552 struct PathCache *item = NULL;
553 struct PathCache *nextItem = NULL;
554
555 if (dir == NULL) {
556 return -EINVAL;
557 }
558
559 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &vp->childPathCaches, struct PathCache, childEntry) {
560 if (i < dir->fd_position) {
561 i++;
562 continue;
563 }
564
565 idx = i - dir->fd_position;
566
567 dstNameSize = sizeof(dir->fd_dir[idx].d_name);
568 result = strncpy_s(dir->fd_dir[idx].d_name, dstNameSize, item->name, item->nameLen);
569 if (result != EOK) {
570 return -ENAMETOOLONG;
571 }
572 dir->fd_dir[idx].d_off = i;
573 dir->fd_dir[idx].d_reclen = (uint16_t)sizeof(struct dirent);
574
575 i++;
576 if (++cnt >= dir->read_cnt) {
577 break;
578 }
579 }
580
581 dir->fd_position = i;
582
583 return cnt;
584}
585
586int VnodeOpendir(struct Vnode *vnode, struct fs_dirent_s *dir)
587{
588 (void)vnode;
589 (void)dir;
590 return LOS_OK;
591}
592
593int VnodeClosedir(struct Vnode *vnode, struct fs_dirent_s *dir)
594{
595 (void)vnode;
596 (void)dir;
597 return LOS_OK;
598}
599///创建节点
600int VnodeCreate(struct Vnode *parent, const char *name, int mode, struct Vnode **vnode)
601{
602 int ret;
603 struct Vnode *newVnode = NULL;
604
605 ret = VnodeAlloc(NULL, &newVnode);//分配一个节点
606 if (ret != 0) {
607 return -ENOMEM;
608 }
609 //继承老爹的基因.
610 newVnode->type = VNODE_TYPE_CHR;//默认是字符设备
611 newVnode->vop = parent->vop;//继承父节点 vop 驱动程序(也叫接口实现)
612 newVnode->fop = parent->fop;//继承父节点 fop 驱动程序(也叫接口实现)
613 newVnode->data = NULL; //默认值
614 newVnode->parent = parent; //指定父节点
615 newVnode->originMount = parent->originMount; //继承父节点挂载信息
616 newVnode->uid = parent->uid; //用户ID
617 newVnode->gid = parent->gid; //用户组ID
618 newVnode->mode = mode;
619 /* The 'name' here is not full path, but for device we don't depend on this path, it's just a name for DFx.
620 When we have devfs, we can get a fullpath. */
621 newVnode->filePath = strdup(name);
622
623 *vnode = newVnode;
624 return 0;
625}
626///设备初始化,设备结点:/dev目录下,对应一个设备,如/dev/mmcblk0
628{
629 struct Vnode *devNode = NULL;
630 struct Mount *devMount = NULL;
631
632 int retval = VnodeLookup("/dev", &devNode, V_CREATE | V_DUMMY);
633 if (retval != LOS_OK) {
634 PRINT_ERR("VnodeDevInit failed error %d\n", retval);
635 return retval;
636 }
637 devNode->mode = DEV_VNODE_MODE | S_IFDIR; // 40755(chmod 755)
638 devNode->type = VNODE_TYPE_DIR; //设备根节点目录
639
640 devMount = MountAlloc(devNode, NULL);//分配一个mount节点
641 if (devMount == NULL) {
642 PRINT_ERR("VnodeDevInit failed mount point alloc failed.\n");
643 return -ENOMEM;
644 }
645 devMount->vnodeCovered = devNode;
646 devMount->vnodeBeCovered->flag |= VNODE_FLAG_MOUNT_ORIGIN;
647 return LOS_OK;
648}
649///buf 接走 vnode 属性
650int VnodeGetattr(struct Vnode *vnode, struct stat *buf)
651{
652 (void)memset_s(buf, sizeof(struct stat), 0, sizeof(struct stat));
653 buf->st_mode = vnode->mode;
654 buf->st_uid = vnode->uid;
655 buf->st_gid = vnode->gid;
656
657 return LOS_OK;
658}
659
661{
662 return g_rootVnode;
663}
664
665static int VnodeChattr(struct Vnode *vnode, struct IATTR *attr)
666{
667 mode_t tmpMode;
668 if (vnode == NULL || attr == NULL) {
669 return -EINVAL;
670 }
671 if (attr->attr_chg_valid & CHG_MODE) {
672 tmpMode = attr->attr_chg_mode;
673 tmpMode &= ~S_IFMT;
674 vnode->mode &= S_IFMT;
675 vnode->mode = tmpMode | vnode->mode;
676 }
677 if (attr->attr_chg_valid & CHG_UID) {
678 vnode->uid = attr->attr_chg_uid;
679 }
680 if (attr->attr_chg_valid & CHG_GID) {
681 vnode->gid = attr->attr_chg_gid;
682 }
683 return LOS_OK;
684}
685
686int VnodeDevLookup(struct Vnode *parentVnode, const char *path, int len, struct Vnode **vnode)
687{
688 (void)parentVnode;
689 (void)path;
690 (void)len;
691 (void)vnode;
692 /* dev node must in pathCache. */
693 return -ENOENT;
694}
695///设备文件系统节点操作
696static struct VnodeOps g_devfsOps = {
698 .Getattr = VnodeGetattr,
699 .Readdir = VnodeReaddir,
700 .Opendir = VnodeOpendir,
701 .Closedir = VnodeClosedir,
702 .Create = VnodeCreate,
703 .Chattr = VnodeChattr,
704};
705//打印索引节点综合信息,总数和内存使用情况
707{
708 struct Vnode *item = NULL;
709 struct Vnode *nextItem = NULL;
710 int vnodeCount = 0;
711 //遍历链表
712 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &g_vnodeActiveList, struct Vnode, actFreeEntry) {
713 if ((item->useCount > 0) ||
714 (item->flag & VNODE_FLAG_MOUNT_ORIGIN) ||
715 (item->flag & VNODE_FLAG_MOUNT_NEW)) {//有效节点
716 continue;
717 }
718
719 vnodeCount++;//统计数量
720 }
721
722 PRINTK("Vnode number = %d\n", vnodeCount);
723 PRINTK("Vnode memory size = %d(B)\n", vnodeCount * sizeof(struct Vnode));
724}
725
727{
728 return &g_vnodeFreeList;
729}
730
732{
733 return &g_vnodeVirtualList;
734}
735
737{
738 return &g_vnodeActiveList;
739}
740
742{
743 struct Vnode *item = NULL;
744 struct Vnode *nextItem = NULL;
745 int count = 0;
746
747 VnodeHold();
748 LOS_DL_LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &g_vnodeActiveList, struct Vnode, actFreeEntry) {
749 if ((item->useCount > 0) ||
750 (item->flag & VNODE_FLAG_MOUNT_ORIGIN) ||
751 (item->flag & VNODE_FLAG_MOUNT_NEW)) {
752 continue;
753 }
754
755 if (VnodeFree(item) == LOS_OK) {
756 count++;
757 }
758 }
759 VnodeDrop();
760
761 return count;
762}
int vfs_normalize_path(const char *directory, const char *filename, char **pathname)
Definition: fullpath.c:245
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListInit(LOS_DL_LIST *list)
Definition: los_list.h:104
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListTailInsert(LOS_DL_LIST *list, LOS_DL_LIST *node)
Insert a node to the tail of a doubly linked list.
Definition: los_list.h:244
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
Definition: los_list.h:292
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListAdd(LOS_DL_LIST *list, LOS_DL_LIST *node)
Insert a new node to a doubly linked list.
Definition: los_list.h:217
LITE_OS_SEC_ALW_INLINE STATIC INLINE BOOL LOS_ListEmpty(LOS_DL_LIST *list)
Identify whether a specified doubly linked list is empty. | 判断链表是否为空
Definition: los_list.h:321
LITE_OS_SEC_TEXT UINT32 LOS_MuxInit(LosMux *mutex, const LosMuxAttr *attr)
初始化互斥锁
Definition: los_mux.c:262
LITE_OS_SEC_TEXT UINT32 LOS_MuxUnlock(LosMux *mutex)
释放锁
Definition: los_mux.c:559
LITE_OS_SEC_TEXT UINT32 LOS_MuxLock(LosMux *mutex, UINT32 timeout)
拿互斥锁,
Definition: los_mux.c:437
VOID LOS_SpinInit(SPIN_LOCK_S *lock)
Definition: los_spinlock.c:37
size_t BOOL
Definition: los_typedef.h:88
void * zalloc(size_t size)
Definition: malloc.c:91
void * malloc(size_t size)
动态分配内存块大小
Definition: malloc.c:81
void free(void *ptr)
释放ptr所指向的内存空间
Definition: malloc.c:66
struct Mount * MountAlloc(struct Vnode *vnode, struct MountOps *mop)
Definition: mount.c:48
void VnodePathCacheFree(struct Vnode *vnode)
和长辈,晚辈告别,从此不再是父亲和孩子.
Definition: path_cache.c:199
int PathCacheFree(struct PathCache *cache)
Definition: path_cache.c:147
int PathCacheLookup(struct Vnode *parent, const char *name, int len, struct Vnode **vnode)
Definition: path_cache.c:162
struct PathCache * PathCacheAlloc(struct Vnode *parent, struct Vnode *vnode, const char *name, uint8_t len)
Definition: path_cache.c:112
此结构用于记录 vnode 的属性
Definition: vnode.h:81
unsigned attr_chg_uid
用户ID
Definition: vnode.h:86
unsigned attr_chg_mode
确定了文件的类型,以及它的所有者、它的group、其它用户访问此文件的权限 (S_IWUSR | ...)
Definition: vnode.h:85
unsigned attr_chg_gid
组ID
Definition: vnode.h:87
unsigned int attr_chg_valid
节点改变有效性 (CHG_MODE | CHG_UID | ... )
Definition: vnode.h:83
举例: mount /dev/mmcblk0p0 /bin1/vs/sd vfat 将/dev/mmcblk0p0 挂载到/bin1/vs/sd目录
Definition: mount.h:68
struct Vnode * vnodeCovered
Definition: mount.h:72
struct Vnode * vnodeBeCovered
Definition: mount.h:71
Definition: los_mux.h:73
struct Vnode * childVnode
Definition: path_cache.h:40
LIST_ENTRY childEntry
Definition: path_cache.h:42
uint8_t nameLen
Definition: path_cache.h:44
char name[0]
Definition: path_cache.h:48
vnode并不包含文件名,因为 vnode和文件名是 1:N 的关系
Definition: vnode.h:164
uint gid
Definition: vnode.h:169
struct Mount * newMount
Definition: vnode.h:181
enum VnodeType type
Definition: vnode.h:165
struct page_mapping mapping
Definition: vnode.h:183
struct VnodeOps * vop
Definition: vnode.h:174
uint32_t flag
Definition: vnode.h:177
mode_t mode
Definition: vnode.h:170
int useCount
Definition: vnode.h:166
void * data
Definition: vnode.h:176
LIST_HEAD childPathCaches
Definition: vnode.h:172
char * filePath
Definition: vnode.h:182
LIST_ENTRY hashEntry
Definition: vnode.h:178
struct file_operations_vfs * fop
Definition: vnode.h:175
struct Mount * originMount
Definition: vnode.h:180
LIST_ENTRY actFreeEntry
Definition: vnode.h:179
uint uid
Definition: vnode.h:168
LIST_HEAD parentPathCaches
Definition: vnode.h:171
struct Vnode * parent
Definition: vnode.h:173
int(* Lookup)(struct Vnode *parent, const char *name, int len, struct Vnode **vnode)
查询节点
Definition: vnode.h:191
int(* Reclaim)(struct Vnode *vnode)
回 收节点
Definition: vnode.h:197
SPIN_LOCK_S list_lock
LOS_DL_LIST page_list
struct file * host
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 void
ARG_NUM_3 ARG_NUM_1 ARG_NUM_2 ARG_NUM_2 ARG_NUM_3 ARG_NUM_1 ARG_NUM_4 ARG_NUM_2 ARG_NUM_2 ARG_NUM_5 ARG_NUM_2 ARG_NUM_0 ARG_NUM_2 ARG_NUM_1 ARG_NUM_2 ARG_NUM_3 ARG_NUM_7 ARG_NUM_2 ARG_NUM_3 ARG_NUM_2 ARG_NUM_4 ARG_NUM_5 ARG_NUM_6 ARG_NUM_3 ARG_NUM_5 ARG_NUM_7 ARG_NUM_1 ARG_NUM_4 ARG_NUM_5 ARG_NUM_4 ARG_NUM_7 ARG_NUM_2 ARG_NUM_3 ARG_NUM_7 ARG_NUM_7 ARG_NUM_3 ARG_NUM_3 ARG_NUM_3 ARG_NUM_7 ARG_NUM_3 ARG_NUM_2 char ARG_NUM_2 ARG_NUM_1 ARG_NUM_0 ARG_NUM_0 ARG_NUM_3 void ARG_NUM_1 ARG_NUM_0 unsigned ARG_NUM_0 ARG_NUM_2 ARG_NUM_3 ARG_NUM_2 ARG_NUM_5 ARG_NUM_3 ARG_NUM_3 ARG_NUM_4 ARG_NUM_1 ARG_NUM_1 ARG_NUM_3 ARG_NUM_2 mode_t
@ VNODE_TYPE_DIR
Definition: vnode.h:137
@ VNODE_TYPE_CHR
Definition: vnode.h:139
@ VNODE_TYPE_UNKNOWN
Definition: vnode.h:135
@ VNODE_TYPE_REG
Definition: vnode.h:136
int VfsVnodePermissionCheck(const struct Vnode *node, int accMode)
Definition: vfs_other.c:80
static int g_freeVnodeSize
Definition: vnode.c:44
int VnodesInit(void)
Definition: vnode.c:91
static int ProcessVirtualVnode(struct Vnode *parent, uint32_t flags, struct Vnode **vnode)
Definition: vnode.c:350
LIST_HEAD * GetVnodeFreeList()
Definition: vnode.c:726
int VnodeClearCache()
Definition: vnode.c:741
LIST_HEAD * GetVnodeVirtualList()
Definition: vnode.c:731
BOOL VnodeInUseIter(const struct Mount *mount)
mount是否正在被某个索引节点使用
Definition: vnode.c:269
static int g_totalVnodeSize
Definition: vnode.c:45
int VnodeCreate(struct Vnode *parent, const char *name, int mode, struct Vnode **vnode)
创建节点
Definition: vnode.c:600
static struct VnodeOps g_devfsOps
设备文件节点操作
Definition: vnode.c:49
int VnodeLookupFullpath(const char *fullpath, struct Vnode **vnode, uint32_t flags)
根节点内部改变
Definition: vnode.c:496
int VnodeFree(struct Vnode *vnode)
是否 vnode 节点
Definition: vnode.c:212
int VnodeDevLookup(struct Vnode *parentVnode, const char *path, int len, struct Vnode **vnode)
Definition: vnode.c:686
static struct Vnode * ConvertVnodeIfMounted(struct Vnode *vnode)
Definition: vnode.c:332
int VnodeFreeAll(const struct Mount *mount)
释放mount下所有的索引节点
Definition: vnode.c:251
static int PreProcess(const char *originPath, struct Vnode **startVnode, char **path)
处理前的准备
Definition: vnode.c:318
int VnodeLookupAt(const char *path, struct Vnode **result, uint32_t flags, struct Vnode *orgVnode)
通过路径 查找索引节点.路径和节点是 N:1的关系, 硬链接
Definition: vnode.c:412
LIST_HEAD * GetVnodeActiveList()
Definition: vnode.c:736
static char * NextName(char *pos, uint8_t *len)
Definition: vnode.c:301
int VnodeDrop()
归还锁
Definition: vnode.c:292
LIST_HEAD g_vnodeFreeList
@ver
Definition: vnode.c:41
LIST_HEAD g_vnodeVirtualList
Definition: vnode.c:42
int VnodeHold()
拿锁,封装互斥量
Definition: vnode.c:283
LIST_HEAD g_vnodeActiveList
Definition: vnode.c:43
static void RefreshLRU(struct Vnode *vnode)
刷新虚拟节点
Definition: vnode.c:340
static int VnodeReaddir(struct Vnode *vp, struct fs_dirent_s *dir)
Definition: vnode.c:544
int VnodeDevInit()
设备初始化,设备结点:/dev目录下,对应一个设备,如/dev/mmcblk0
Definition: vnode.c:627
static int VnodeChattr(struct Vnode *vnode, struct IATTR *attr)
Definition: vnode.c:665
void ChangeRoot(struct Vnode *rootNew)
改变根节点
Definition: vnode.c:536
static void ChangeRootInternal(struct Vnode *rootOld, char *dirname)
Definition: vnode.c:501
int VnodeClosedir(struct Vnode *vnode, struct fs_dirent_s *dir)
Definition: vnode.c:593
static struct Vnode * g_rootVnode
根节点
Definition: vnode.c:48
int VnodeAlloc(struct VnodeOps *vop, struct Vnode **newVnode)
申请分配一个 vnode 节点,vop为操作节点的驱动程序
Definition: vnode.c:166
int VnodeOpendir(struct Vnode *vnode, struct fs_dirent_s *dir)
Definition: vnode.c:586
static LosMux g_vnodeMux
操作链表互斥量
Definition: vnode.c:47
int VnodeGetattr(struct Vnode *vnode, struct stat *buf)
buf 接走 vnode 属性
Definition: vnode.c:650
static struct Vnode * GetFromFreeList(void)
获取空闲节点链表,分配的节点从空闲链表里出
Definition: vnode.c:114
struct Vnode * VnodeReclaimLru(void)
节点批量回收, LRU是Least Recently Used的缩写,即最近最少使用,
Definition: vnode.c:133
void VnodeMemoryDump(void)
Definition: vnode.c:706
int VnodeLookup(const char *path, struct Vnode **vnode, uint32_t flags)
通过路径查询vnode节点
Definition: vnode.c:491
static int Step(char **currentDir, struct Vnode **currentVnode, uint32_t flags)
一级一级向下找
Definition: vnode.c:363
struct Vnode * VnodeGetRoot()
Definition: vnode.c:660