更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
vnode.h 文件参考

浏览源代码.

结构体

struct  IATTR
 此结构用于记录 vnode 的属性 更多...
 
struct  Vnode
 vnode并不包含文件名,因为 vnode和文件名是 1:N 的关系 更多...
 
struct  VnodeOps
 

类型定义

typedef LOS_DL_LIST LIST_HEAD
 
typedef LOS_DL_LIST LIST_ENTRY
 
typedef int VfsHashCmp(struct Vnode *vnode, void *arg)
 

枚举

enum  VnodeType {
  VNODE_TYPE_UNKNOWN , VNODE_TYPE_REG , VNODE_TYPE_DIR , VNODE_TYPE_BLK ,
  VNODE_TYPE_CHR , VNODE_TYPE_BCHR , VNODE_TYPE_FIFO , VNODE_TYPE_LNK
}
 

函数

int VnodesInit (void)
 
int VnodeDevInit (void)
 设备初始化,设备结点:/dev目录下,对应一个设备,如/dev/mmcblk0 更多...
 
int VnodeAlloc (struct VnodeOps *vop, struct Vnode **vnode)
 申请分配一个 vnode 节点,vop为操作节点的驱动程序 更多...
 
int VnodeFree (struct Vnode *vnode)
 是否 vnode 节点 更多...
 
int VnodeLookup (const char *path, struct Vnode **vnode, uint32_t flags)
 通过路径查询vnode节点 更多...
 
int VnodeLookupFullpath (const char *fullpath, struct Vnode **vnode, uint32_t flags)
 根节点内部改变 更多...
 
int VnodeLookupAt (const char *path, struct Vnode **vnode, uint32_t flags, struct Vnode *orgVnode)
 通过路径 查找索引节点.路径和节点是 N:1的关系, 硬链接 更多...
 
int VnodeHold (void)
 拿锁,封装互斥量 更多...
 
int VnodeDrop (void)
 归还锁 更多...
 
void VnodeRefDec (struct Vnode *vnode)
 
int VnodeFreeAll (const struct Mount *mnt)
 释放mount下所有的索引节点 更多...
 
int VnodeHashInit (void)
 
uint32_t VfsHashIndex (struct Vnode *vnode)
 通过节点获取哈希索引值 更多...
 
int VfsHashGet (const struct Mount *mount, uint32_t hash, struct Vnode **vnode, VfsHashCmp *fun, void *arg)
 通过哈希值获取节点信息 更多...
 
void VfsHashRemove (struct Vnode *vnode)
 从哈希链表中摘除索引节点 更多...
 
int VfsHashInsert (struct Vnode *vnode, uint32_t hash)
 插入哈希表 更多...
 
void ChangeRoot (struct Vnode *newRoot)
 改变根节点 更多...
 
BOOL VnodeInUseIter (const struct Mount *mount)
 mount是否正在被某个索引节点使用 更多...
 
struct VnodeVnodeGetRoot (void)
 
void VnodeMemoryDump (void)
 
mode_t GetUmask (void)
 获取用户创建文件掩码 更多...
 
int VfsPermissionCheck (uint fuid, uint fgid, mode_t fileMode, int accMode)
 
int VfsVnodePermissionCheck (const struct Vnode *node, int accMode)
 
LIST_HEADGetVnodeFreeList (void)
 
LIST_HEADGetVnodeActiveList (void)
 
LIST_HEADGetVnodeVirtualList (void)
 
int VnodeClearCache (void)
 

类型定义说明

◆ LIST_ENTRY

在文件 vnode.h40 行定义.

◆ LIST_HEAD

在文件 vnode.h39 行定义.

◆ VfsHashCmp

typedef int VfsHashCmp(struct Vnode *vnode, void *arg)

哈希比较指针函数,使用方法,例如: int VfsHashGet(const struct Mount *mount, uint32_t hash, struct Vnode **vnode, VfsHashCmp *fn, void *arg) VfsHashCmp *fn 等同于 int *fn, 此时 fn是个指针,指向了一个函数地址 fn(vnode,arg)就是调用这个函数,返回一个int类型的值

在文件 vnode.h228 行定义.

枚举类型说明

◆ VnodeType

enum VnodeType
Linux系统使用struct inode作为数据结构名称。BSD派生的系统,使用vnode名称,其中v表示“virtual file system”
Linux 链接分两种,一种被称为硬链接(Hard Link),另一种被称为符号链接(Symbolic Link)。默认情况下,ln 命令产生硬链接。

硬连接
    硬连接指通过索引节点来进行连接。在 Linux 的文件系统中,保存在磁盘分区中的文件不管是什么类型都给它分配一个编号,
    称为索引节点号(Inode Index)。在 Linux 中,多个文件名指向同一索引节点是存在的。比如:A 是 B 的硬链接(A 和 B 都是文件名),
    则 A 的目录项中的 inode 节点号与 B 的目录项中的 inode 节点号相同,即一个 inode 节点对应两个不同的文件名,两个文件名指向同一个文件,
    A 和 B 对文件系统来说是完全平等的。删除其中任何一个都不会影响另外一个的访问。
    硬连接的作用是允许一个文件拥有多个有效路径名,这样用户就可以建立硬连接到重要文件,以防止“误删”的功能。其原因如上所述,
    因为对应该目录的索引节点有一个以上的连接。只删除一个连接并不影响索引节点本身和其它的连接,只有当最后一个连接被删除后,
    文件的数据块及目录的连接才会被释放。也就是说,文件真正删除的条件是与之相关的所有硬连接文件均被删除。
    # ln 源文件 目标文件
    
软连接
    另外一种连接称之为符号连接(Symbolic Link),也叫软连接。软链接文件有类似于 Windows 的快捷方式。
    它实际上是一个特殊的文件。在符号连接中,文件实际上是一个文本文件,其中包含的有另一文件的位置信息。
    比如:A 是 B 的软链接(A 和 B 都是文件名),A 的目录项中的 inode 节点号与 B 的目录项中的 inode 节点号不相同,
    A 和 B 指向的是两个不同的 inode,继而指向两块不同的数据块。但是 A 的数据块中存放的只是 B 的路径名(可以根据这个找到 B 的目录项)。
    A 和 B 之间是“主从”关系,如果 B 被删除了,A 仍然存在(因为两个是不同的文件),但指向的是一个无效的链接。
    # ln -s 源文文件或目录 目标文件或目录
    
软链接与硬链接最大的不同:文件A指向文件B的文件名,而不是文件B的inode号码,文件B的inode"链接数"不会因此发生变化。    

inode的特殊作用
由于inode号码与文件名分离,这种机制导致了一些Unix/Linux系统特有的现象。
  1. 有时,文件名包含特殊字符,无法正常删除。这时,直接删除inode节点,就能起到删除文件的作用。
  2. 移动文件或重命名文件,只是改变文件名,不影响inode号码。
  3. 打开一个文件以后,系统就以inode号码来识别这个文件,不再考虑文件名。因此,通常来说,系统无法从inode号码得知文件名。
第3点使得软件更新变得简单,可以在不关闭软件的情况下进行更新,不需要重启。因为系统通过inode号码,识别运行中的文件,不通过文件名。
更新的时候,新版文件以同样的文件名,生成一个新的inode,不会影响到运行中的文件。等到下一次运行这个软件的时候,文件名就自动指向新版文件,
旧版文件的inode则被回收。

Vnode types. VNODE_TYPE_UNKNOWN means no type. | 节点类型

枚举值
VNODE_TYPE_UNKNOWN 
VNODE_TYPE_REG 

unknown type | 未知类型

VNODE_TYPE_DIR 

regular file | 正则文件(普通文件)

VNODE_TYPE_BLK 

directory | 目录

VNODE_TYPE_CHR 

block device | 块设备

VNODE_TYPE_BCHR 

char device | 字符设备

VNODE_TYPE_FIFO 

block char mix device | 块和字符设备混合

VNODE_TYPE_LNK 

pipe | 管道文件

在文件 vnode.h134 行定义.

134 {
135 VNODE_TYPE_UNKNOWN, /*! unknown type | 未知类型*/
136 VNODE_TYPE_REG, /*! regular file | 正则文件(普通文件)*/
137 VNODE_TYPE_DIR, /*! directory | 目录*/
138 VNODE_TYPE_BLK, /*! block device | 块设备*/
139 VNODE_TYPE_CHR, /*! char device | 字符设备*/
140 VNODE_TYPE_BCHR, /*! block char mix device | 块和字符设备混合*/
141 VNODE_TYPE_FIFO, /*! pipe | 管道文件*/
142 VNODE_TYPE_LNK, /*! link | 链接,这里的链接指的是上层硬链接概念*/
143};
@ VNODE_TYPE_LNK
Definition: vnode.h:142
@ VNODE_TYPE_DIR
Definition: vnode.h:137
@ VNODE_TYPE_FIFO
Definition: vnode.h:141
@ VNODE_TYPE_CHR
Definition: vnode.h:139
@ VNODE_TYPE_BLK
Definition: vnode.h:138
@ VNODE_TYPE_UNKNOWN
Definition: vnode.h:135
@ VNODE_TYPE_REG
Definition: vnode.h:136
@ VNODE_TYPE_BCHR
Definition: vnode.h:140

函数说明

◆ ChangeRoot()

void ChangeRoot ( struct Vnode newRoot)

改变根节点

在文件 vnode.c536 行定义.

537{
538 struct Vnode *rootOld = g_rootVnode;
539 g_rootVnode = rootNew;
540 ChangeRootInternal(rootOld, "proc");
541 ChangeRootInternal(rootOld, "dev");
542}
vnode并不包含文件名,因为 vnode和文件名是 1:N 的关系
Definition: vnode.h:164
static void ChangeRootInternal(struct Vnode *rootOld, char *dirname)
Definition: vnode.c:501
static struct Vnode * g_rootVnode
根节点
Definition: vnode.c:48
函数调用图:

◆ GetUmask()

mode_t GetUmask ( void  )

获取用户创建文件掩码

在文件 vfs_other.c715 行定义.

716{
717 return OsCurrProcessGet()->umask;
718}
STATIC INLINE LosProcessCB * OsCurrProcessGet(VOID)
mode_t umask
umask(user file-creatiopn mode mask)为用户文件创建掩码,是创建文件或文件夹时默认权限的基础。
函数调用图:
这是这个函数的调用关系图:

◆ GetVnodeActiveList()

LIST_HEAD * GetVnodeActiveList ( void  )

在文件 vnode.c736 行定义.

737{
738 return &g_vnodeActiveList;
739}
LIST_HEAD g_vnodeActiveList
Definition: vnode.c:43
这是这个函数的调用关系图:

◆ GetVnodeFreeList()

LIST_HEAD * GetVnodeFreeList ( void  )

在文件 vnode.c726 行定义.

727{
728 return &g_vnodeFreeList;
729}
LIST_HEAD g_vnodeFreeList
@ver
Definition: vnode.c:41
这是这个函数的调用关系图:

◆ GetVnodeVirtualList()

LIST_HEAD * GetVnodeVirtualList ( void  )

在文件 vnode.c731 行定义.

732{
733 return &g_vnodeVirtualList;
734}
LIST_HEAD g_vnodeVirtualList
Definition: vnode.c:42
这是这个函数的调用关系图:

◆ VfsHashGet()

int VfsHashGet ( const struct Mount mount,
uint32_t  hash,
struct Vnode **  vnode,
VfsHashCmp fun,
void arg 
)

通过哈希值获取节点信息

在文件 vnode_hash.c89 行定义.

90{
91 struct Vnode *curVnode = NULL;
92
93 if (mount == NULL || vnode == NULL) {
94 return -EINVAL;
95 }
96
97 (void)LOS_MuxLock(&g_vnodeHashMux, LOS_WAIT_FOREVER);//先上锁
98 LOS_DL_LIST *list = VfsHashBucket(mount, hash);//获取哈希表对应的链表项
99 LOS_DL_LIST_FOR_EACH_ENTRY(curVnode, list, struct Vnode, hashEntry) {//遍历链表
100 if (curVnode->hash != hash) {//对比哈希值找
101 continue;
102 }
103 if (curVnode->originMount != mount) {//对比原始mount值必须一致
104 continue;
105 }
106 if (fn != NULL && fn(curVnode, arg)) {//哈希值比较函数,fn由具体的文件系统提供.
107 continue;
108 }
110 *vnode = curVnode;//找到对应索引节点
111 return LOS_OK;
112 }
114 *vnode = NULL;
115 return LOS_NOK;
116}
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
uint32_t hash
Definition: vnode.h:167
LIST_ENTRY hashEntry
Definition: vnode.h:178
struct Mount * originMount
Definition: vnode.h:180
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
static LOS_DL_LIST * VfsHashBucket(const struct Mount *mp, uint32_t hash)
通过哈希值和装载设备哈希种子获取哈希表索引
Definition: vnode_hash.c:84
static LosMux g_vnodeHashMux
Definition: vnode_hash.c:42
函数调用图:
这是这个函数的调用关系图:

◆ VfsHashIndex()

uint32_t VfsHashIndex ( struct Vnode vnode)

通过节点获取哈希索引值

在文件 vnode_hash.c76 行定义.

77{
78 if (vnode == NULL) {
79 return -EINVAL;
80 }
81 return (vnode->hash + vnode->originMount->hashseed);//用于定位在哈希表的下标
82}
uint32_t hashseed
Definition: mount.h:79

◆ VfsHashInsert()

int VfsHashInsert ( struct Vnode vnode,
uint32_t  hash 
)

插入哈希表

在文件 vnode_hash.c128 行定义.

129{
130 if (vnode == NULL) {
131 return -EINVAL;
132 }
133 (void)LOS_MuxLock(&g_vnodeHashMux, LOS_WAIT_FOREVER);
134 vnode->hash = hash;//设置节点哈希值
135 LOS_ListHeadInsert(VfsHashBucket(vnode->originMount, hash), &vnode->hashEntry);//通过节点hashEntry 挂入哈希表对于索引链表中
137 return LOS_OK;
138}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListHeadInsert(LOS_DL_LIST *list, LOS_DL_LIST *node)
Insert a node to the head of a doubly linked list.
Definition: los_list.h:268
函数调用图:
这是这个函数的调用关系图:

◆ VfsHashRemove()

void VfsHashRemove ( struct Vnode vnode)

从哈希链表中摘除索引节点

在文件 vnode_hash.c118 行定义.

119{
120 if (vnode == NULL) {
121 return;
122 }
123 (void)LOS_MuxLock(&g_vnodeHashMux, LOS_WAIT_FOREVER);
124 LOS_ListDelete(&vnode->hashEntry);//直接把自己摘掉就行了
126}
LITE_OS_SEC_ALW_INLINE STATIC INLINE VOID LOS_ListDelete(LOS_DL_LIST *node)
Definition: los_list.h:292
函数调用图:

◆ VfsPermissionCheck()

int VfsPermissionCheck ( uint  fuid,
uint  fgid,
mode_t  fileMode,
int  accMode 
)
这是这个函数的调用关系图:

◆ VfsVnodePermissionCheck()

int VfsVnodePermissionCheck ( const struct Vnode node,
int  accMode 
)

在文件 vfs_other.c80 行定义.

81{
82 uint fuid = node->uid;
83 uint fgid = node->gid;
84 uint fileMode = node->mode;
85 return VfsPermissionCheck(fuid, fgid, fileMode, accMode);
86}
uint gid
Definition: vnode.h:169
mode_t mode
Definition: vnode.h:170
uint uid
Definition: vnode.h:168
int VfsPermissionCheck(uint fuid, uint fgid, uint fileMode, int accMode)
Definition: vfs_other.c:87
函数调用图:
这是这个函数的调用关系图:

◆ VnodeAlloc()

int VnodeAlloc ( struct VnodeOps vop,
struct Vnode **  vnode 
)

申请分配一个 vnode 节点,vop为操作节点的驱动程序

在文件 vnode.c166 行定义.

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}
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_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_TEXT UINT32 LOS_MuxInit(LosMux *mutex, const LosMuxAttr *attr)
初始化互斥锁
Definition: los_mux.c:262
VOID LOS_SpinInit(SPIN_LOCK_S *lock)
Definition: los_spinlock.c:37
void * zalloc(size_t size)
Definition: malloc.c:91
enum VnodeType type
Definition: vnode.h:165
struct page_mapping mapping
Definition: vnode.h:183
struct VnodeOps * vop
Definition: vnode.h:174
LIST_HEAD childPathCaches
Definition: vnode.h:172
LIST_ENTRY actFreeEntry
Definition: vnode.h:179
LIST_HEAD parentPathCaches
Definition: vnode.h:171
SPIN_LOCK_S list_lock
LOS_DL_LIST page_list
struct file * host
static int g_totalVnodeSize
Definition: vnode.c:45
static struct VnodeOps g_devfsOps
设备文件节点操作
Definition: vnode.c:49
int VnodeDrop()
归还锁
Definition: vnode.c:292
int VnodeHold()
拿锁,封装互斥量
Definition: vnode.c:283
static struct Vnode * GetFromFreeList(void)
获取空闲节点链表,分配的节点从空闲链表里出
Definition: vnode.c:114
struct Vnode * VnodeReclaimLru(void)
节点批量回收, LRU是Least Recently Used的缩写,即最近最少使用,
Definition: vnode.c:133
函数调用图:
这是这个函数的调用关系图:

◆ VnodeClearCache()

int VnodeClearCache ( void  )

在文件 vnode.c741 行定义.

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}
uint32_t flag
Definition: vnode.h:177
int useCount
Definition: vnode.h:166
int VnodeFree(struct Vnode *vnode)
是否 vnode 节点
Definition: vnode.c:212
函数调用图:
这是这个函数的调用关系图:

◆ VnodeDevInit()

int VnodeDevInit ( void  )

设备初始化,设备结点:/dev目录下,对应一个设备,如/dev/mmcblk0

在文件 vnode.c627 行定义.

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}
struct Mount * MountAlloc(struct Vnode *vnode, struct MountOps *mop)
Definition: mount.c:48
举例: 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
int VnodeLookup(const char *path, struct Vnode **vnode, uint32_t flags)
通过路径查询vnode节点
Definition: vnode.c:491
函数调用图:
这是这个函数的调用关系图:

◆ VnodeDrop()

int VnodeDrop ( void  )

归还锁

在文件 vnode.c292 行定义.

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}
static LosMux g_vnodeMux
操作链表互斥量
Definition: vnode.c:47
函数调用图:
这是这个函数的调用关系图:

◆ VnodeFree()

int VnodeFree ( struct Vnode vnode)

是否 vnode 节点

在文件 vnode.c212 行定义.

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}
void free(void *ptr)
释放ptr所指向的内存空间
Definition: malloc.c:66
void VnodePathCacheFree(struct Vnode *vnode)
和长辈,晚辈告别,从此不再是父亲和孩子.
Definition: path_cache.c:199
void * data
Definition: vnode.h:176
char * filePath
Definition: vnode.h:182
int(* Reclaim)(struct Vnode *vnode)
回 收节点
Definition: vnode.h:197
static int g_freeVnodeSize
Definition: vnode.c:44
函数调用图:
这是这个函数的调用关系图:

◆ VnodeFreeAll()

int VnodeFreeAll ( const struct Mount mnt)

释放mount下所有的索引节点

在文件 vnode.c251 行定义.

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}
函数调用图:

◆ VnodeGetRoot()

struct Vnode * VnodeGetRoot ( void  )

在文件 vnode.c660 行定义.

661{
662 return g_rootVnode;
663}

◆ VnodeHashInit()

int VnodeHashInit ( void  )

在文件 vnode_hash.c44 行定义.

45{
46 int ret;
47 for (int i = 0; i < g_vnodeHashSize; i++) {//遍历初始化 128个双向链表
49 }
50
51 ret = LOS_MuxInit(&g_vnodeHashMux, NULL);
52 if (ret != LOS_OK) {
53 PRINT_ERR("Create mutex for vnode hash list fail, status: %d", ret);
54 return ret;
55 }
56
57 return LOS_OK;
58}
LIST_HEAD g_vnodeHashEntrys[VNODE_HASH_BUCKETS]
Definition: vnode_hash.c:38
uint32_t g_vnodeHashSize
Definition: vnode_hash.c:40
函数调用图:
这是这个函数的调用关系图:

◆ VnodeHold()

int VnodeHold ( void  )

拿锁,封装互斥量

在文件 vnode.c283 行定义.

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}
函数调用图:
这是这个函数的调用关系图:

◆ VnodeInUseIter()

BOOL VnodeInUseIter ( const struct Mount mount)

mount是否正在被某个索引节点使用

在文件 vnode.c269 行定义.

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}

◆ VnodeLookup()

int VnodeLookup ( const char *  path,
struct Vnode **  vnode,
uint32_t  flags 
)

通过路径查询vnode节点

在文件 vnode.c491 行定义.

492{
493 return VnodeLookupAt(path, vnode, flags, NULL);
494}
int VnodeLookupAt(const char *path, struct Vnode **result, uint32_t flags, struct Vnode *orgVnode)
通过路径 查找索引节点.路径和节点是 N:1的关系, 硬链接
Definition: vnode.c:412
函数调用图:
这是这个函数的调用关系图:

◆ VnodeLookupAt()

int VnodeLookupAt ( const char *  path,
struct Vnode **  vnode,
uint32_t  flags,
struct Vnode orgVnode 
)

通过路径 查找索引节点.路径和节点是 N:1的关系, 硬链接

在文件 vnode.c412 行定义.

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}
void * malloc(size_t size)
动态分配内存块大小
Definition: malloc.c:81
int VfsVnodePermissionCheck(const struct Vnode *node, int accMode)
Definition: vfs_other.c:80
static int PreProcess(const char *originPath, struct Vnode **startVnode, char **path)
处理前的准备
Definition: vnode.c:318
static int Step(char **currentDir, struct Vnode **currentVnode, uint32_t flags)
一级一级向下找
Definition: vnode.c:363
函数调用图:
这是这个函数的调用关系图:

◆ VnodeLookupFullpath()

int VnodeLookupFullpath ( const char *  fullpath,
struct Vnode **  vnode,
uint32_t  flags 
)

根节点内部改变

在文件 vnode.c496 行定义.

497{
498 return VnodeLookupAt(fullpath, vnode, flags, g_rootVnode);
499}
函数调用图:

◆ VnodeMemoryDump()

void VnodeMemoryDump ( void  )

在文件 vnode.c706 行定义.

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}
这是这个函数的调用关系图:

◆ VnodeRefDec()

void VnodeRefDec ( struct Vnode vnode)

◆ VnodesInit()

int VnodesInit ( void  )

#ifndef S_IRUSR #define S_ISUID 04000 #define S_ISGID 02000 #define S_ISVTX 01000 #define S_IRUSR 0400 #define S_IWUSR 0200 #define S_IXUSR 0100 #define S_IRWXU 0700 #define S_IRGRP 0040 #define S_IWGRP 0020 #define S_IXGRP 0010 #define S_IRWXG 0070 #define S_IROTH 0004 #define S_IWOTH 0002 #define S_IXOTH 0001 #define S_IRWXO 0007 #endif

在文件 vnode.c91 行定义.

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}
int VnodeAlloc(struct VnodeOps *vop, struct Vnode **newVnode)
申请分配一个 vnode 节点,vop为操作节点的驱动程序
Definition: vnode.c:166
函数调用图:
这是这个函数的调用关系图: