⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 namei.c

📁 linux的文件系统的部分代码的详细注释
💻 C
📖 第 1 页 / 共 5 页
字号:
	mntput(*mnt);	*mnt = parent;	return 1;}int follow_up(struct vfsmount **mnt, struct dentry **dentry){	/*调用__follow_up函数*/	return __follow_up(mnt, dentry);}/*获得当前文件系统,并赋给nameidata结构的mnt指针,  *并将其根目录赋给dentry*/static inline int __follow_down(struct vfsmount **mnt, struct dentry **dentry){	struct vfsmount *mounted;	/*上锁*/	spin_lock(&dcache_lock);	/**/	mounted = lookup_mnt(*mnt, *dentry);	if (mounted) {		/*获得当前文件系统*/		*mnt = mntget(mounted);		spin_unlock(&dcache_lock);		/*释放dentry*/		dput(*dentry);		/*父目录连接到当前vfsmount的相应指针*/		mntput(mounted->mnt_parent);		/*根目录赋值到dentry*/		*dentry = dget(mounted->mnt_root);		/*成功返回*/		return 1;	}	/*解锁*/	spin_unlock(&dcache_lock);	/*不成功返回为0*/	return 0;}/*调用__follow_down函数*/int follow_down(struct vfsmount **mnt, struct dentry **dentry){	/*返回__follow_down函数调用的结果*/	return __follow_down(mnt,dentry);} /*寻找nameidata描述文件的父目录*/static inline void follow_dotdot(struct nameidata *nd){	while(1) {		/*指向其上层设备的vfsmount的变量*/		struct vfsmount *parent;		/*指向其父目录dentry的变量*/		struct dentry *dentry;		/*读上锁*/		read_lock(&current->fs->lock);		/*已到达 结点是本进程的根结点,dentry和mnt指针都相等*/		if (nd->dentry == current->fs->root &&		    nd->mnt == current->fs->rootmnt)  {		       /*解锁*/			read_unlock(&current->fs->lock);			break;		}		/*解锁*/		read_unlock(&current->fs->lock);		/*实现缓冲区互斥上锁*/		spin_lock(&dcache_lock);		/*已到达的节点nd->dentry与其父结点在同一设备上*/		if (nd->dentry != nd->mnt->mnt_root) {			/*当前节点dentry结构中d_parent指针即指向其父结点的dentry			  *调用dget获得其父节点的dentry*/			dentry = dget(nd->dentry->d_parent);			/*解锁*/			spin_unlock(&dcache_lock);			/*释放当前节点的dentry*/			dput(nd->dentry);			/*将所得父节点的dentry结构纳入到nameidata结构中*/			nd->dentry = dentry;			break;		}		/*当前节点vfsmount结构中mnt_parent指针即指向其上层设备的vfsmount*/		parent=nd->mnt->mnt_parent;		/*已到达结点即是其所在设备上的根节点,表明已是根目录则保持现状跳出循环*/		if (parent == nd->mnt) {			/*解锁*/			spin_unlock(&dcache_lock);			/*跳出循环*/			break;		}		/*已到达结点不是其所在设备根节点的处理,层层向上直到根节点*/		/*获得上层设备的vfsmount*/		mntget(parent);		/*获得上层目录的dentry*/		dentry=dget(nd->mnt->mnt_mountpoint);		/*解锁*/		spin_unlock(&dcache_lock);		/*释放已到达结点的dentry*/		dput(nd->dentry);		/*nameidata结构的dentry指针指向上层目录的dentry*/		nd->dentry = dentry;		/*释放已到达结点的vfsmount*/		mntput(nd->mnt);		/*nameidata结构的dentry指针指向上层设备的vfsmount*/		nd->mnt = parent;	}}/* *顺着路径名查找文件,将查找结果记录到nameidata结构 */int link_path_walk(const char * name, struct nameidata *nd){	/*新建一个dentry结构*/	struct dentry *dentry;		/*新建一个inode结构*/	struct inode *inode;		/*错误标志*/	int err;		/*将namei的寻找方式标记赋值给lookup_flags*/	unsigned int lookup_flags = nd->flags;      /*除去路径名开头的所有'/'*/	while (*name=='/')		name++;		/*路径名中仅含有"/",即其目标就是根目录,任务完成成功返回*/	if (!*name)		goto return_base;		/*inode赋值*/	inode = nd->dentry->d_inode;		/*如果当前文件链不为0,	  *则将查找方式标记设为LOOKUP_FOLLOW,即依次寻找*/	if (current->link_count)		lookup_flags = LOOKUP_FOLLOW;	/* At this point we know we have a real path component. */	for(;;) {		/*哈希变量*/		unsigned long hash;				/*quick string结构*/		struct qstr this;		/*存放目录名中单个字母的变量*/		unsigned int c;		/*检查文件系统对应的inode是否可有“执行”权*/		err = permission(inode, MAY_EXEC);		/*错误类型转化后赋值给dentry*/		dentry = ERR_PTR(err);				/*无“执行权”则跳出循环*/ 		if (err)			break;				/*将目录名赋值给this的成员变量this*/		this.name = this;				/*得到当前节点名中第一个字母*/		c = *(const unsigned char *)name;		/*将哈希值清零*/		hash = init_name_hash();		/*对一层目录名做哈希转化*/		do {			name++;			hash = partial_name_hash(c, hash);			c = *(const unsigned char *)name;		} while (c && (c != '/'));				/*得到进行hash转化的目录名的长度*/		this.len = name - (const char *) this.name;				/*将hash值赋给this.hash,		  *若超过了unsigned int 的长度,再hash*/		this.hash = end_name_hash(hash);		/* 若c为空则跳转到 last_component*/		if (!c)			goto last_component;				/*跳过所有的'/',若为空则跳到last_with_slashes*/		while (*++name == '/');		if (!*name)			goto last_with_slashes;		/*判断this.name的前两位是否以'.'开头		  *如果当前第一个节点以'.'开头则节点名长度只能是1或2		  *当长度为2时,第二个也必为'.'否则搜索失败*/		if (this.name[0] == '.') switch (this.len) {			default:				break;							case 2:					/*搜索失败*/				if (this.name[1] != '.')					break;				/*若有两个'.'				 *则执行follow_dotdot寻找它当前的根目录和父目录*/				follow_dotdot(nd);				/*重设inode的值*/				inode = nd->dentry->d_inode;				/* fallthrough */							/*若只有一个'.'则执行下一次循环			 	 *路径名"/home/./user1"等价于"/home/user1"*/			case 1:				continue;		}		/*如果当前目录项的d_op与d_op的d_hash非空		  *则调用它自己文件系统的d_hash函数*/		if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {			err = nd->dentry->d_op->d_hash(nd->dentry, &this);			/*若出错则跳出当前循环*/			if (err < 0)				break;		}				/*从缓存中寻找当前目录的dentry*/		dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);		/*如果没有找到dentry则需要再一次搜索*/		if (!dentry) {						/*调用real_lookup实现搜索*/			dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);						/*错误类型转化*/			err = PTR_ERR(dentry);						/*判断有错则跳出循环*/			if (IS_ERR(dentry))				break;		}				/* 如果当前目录下挂有文件系统		  *找到它并将其赋给nd->mnt		  *并将其根目录赋给dentry*/		while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))			;		/*错误标记赋值*/		err = -ENOENT;		/*inode赋值*/		inode = dentry->d_inode;				/*若dentry的d_inode为空则跳转到out_dput,即适放资源后返回出错信息*/		if (!inode)			goto out_dput;				/*错误标记赋值*/		err = -ENOTDIR; 		/*若此时inode的i_op为空则不是一个目录结点跳转到out_dput*/		if (!inode->i_op)			goto out_dput;				/*若此节点是文件链接,调用do_follow_link处理链接*/		if (inode->i_op->follow_link) {			err = do_follow_link(dentry, nd);			dput(dentry);			/*有错跳到返回字段*/			if (err)				goto return_err;			err = -ENOENT;			/*新获得inode*/			inode = nd->dentry->d_inode;						/*若dentry的d_inode为空则跳出循环*/			if (!inode)				break;			err = -ENOTDIR; 					/*若此时inode的i_op为空则不是一个目录结点跳出循环*/			if (!inode->i_op)				break;		} 		/*处理普通目录节点*/		else {			/**/			dput(nd->dentry);			/*将得到dentry保存到nd->dentry*/			nd->dentry = dentry;		}		err = -ENOTDIR; 		/*如果inode->i_op->lookup为空则无后续目录结点,跳出循环*/			if (!inode->i_op->lookup)			break;		/*继续循环处理下一层目录*/		continue;		/* here ends the main loop */last_with_slashes:		/*如果文件名路径最后是以'/'结束的,		  *则该将搜索的方式加上LOOKUP_FOLLOW与LOOKUP_FOLLOW*/		lookup_flags |= LOOKUP_FOLLOW | LOOKUP_FOLLOW;last_component:		if (lookup_flags & LOOKUP_PARENT)			goto lookup_parent;		/*以下代码处理路径名最后一项*/		/*判断this.name的前两位是否以'.'开头*/		if (this.name[0] == '.') switch (this.len) {			default:				break;			/*长度为2*/			case 2:									/*搜索失败*/				if (this.name[1] != '.')					break;								/*若有两个'.'				 *则执行follow_dotdot寻找它当前的根目录和父目录*/				follow_dotdot(nd);				/*重设inode的值*/				inode = nd->dentry->d_inode;				/* fallthrough */							/*若只有一个'.'则执行下一次循环			 	 *路径名"/home/./user1"等价于"/home/user1"*/				case 1:				goto return_base;		}				    /*如果当前目录项的d_op与d_op的d_hash非空		      *则调用它自己文件系统的d_hash函数*/		if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {			err = nd->dentry->d_op->d_hash(nd->dentry, &this);						/*若出错则跳出当前循环*/			if (err < 0)				break;		}				/*从缓存中寻找当前目录的dentry*/		dentry = cached_lookup(nd->dentry, &this, 0);			/*如果没有找到dentry则需要再一次搜索*/		if (!dentry) {			/*调用real_lookup实现搜索*/			dentry = real_lookup(nd->dentry, &this, 0);			/*错误类型转化*/			err = PTR_ERR(dentry);			/*判断有错则跳出循环*/			if (IS_ERR(dentry))				break;		}		/* 如果当前目录下挂有文件系统		  *找到它并将其赋给nd->mnt		  *并将其根目录赋给dentry*/		while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))			;		/*inode赋值*/		inode = dentry->d_inode;		/*inode、inode->i_op、inode->i_op->follow_link均不空且		  *其查找标志为LOOKUP_FOLLOW		  *调用do_follow_link处理链接*/		if ((lookup_flags & LOOKUP_FOLLOW)		    && inode && inode->i_op && inode->i_op->follow_link) {		    		    	 /*调用do_follow_link*/			err = do_follow_link(dentry, nd);			dput(dentry);			/*有错跳到返回字段*/			if (err)				goto return_err;			/*新获得inode*/			inode = nd->dentry->d_inode;		} 		/*处理普通目录节点*/		else {			dput(nd->dentry);						/*将得到dentry保存到nd->dentry*/			nd->dentry = dentry;		}		err = -ENOENT;			/*如果inode为空,跳到no_inode字段*/(580)		if (!inode)			goto no_inode;		/*如果查找标志为LOOKUP_DIRECTORY*/		if (lookup_flags & LOOKUP_DIRECTORY) {			err = -ENOTDIR; 			/*inode->i_op或inode->i_op->lookup为空则跳出循环*/			if (!inode->i_op || !inode->i_op->lookup)				break;		}		/*如果查找标志不为LOOKUP_DIRECTORY跳到返回字段*/		goto return_base;/*no_inode字段*/no_inode:		err = -ENOENT;		/*LOOKUP_POSITIVE与LOOKUP_DIRECTORY被置位,出错,跳出循环境污染*/		if (lookup_flags & (LOOKUP_POSITIVE|LOOKUP_DIRECTORY))			break;		/*成功返回*/		goto return_base;/*将当前信息保存到父节点*/lookup_parent:		/*nd->last赋值*/		nd->last = this;		/*nd->last_type赋值*/		nd->last_type = LAST_NORM;		/*若路径名的第一个字母不为'.'*/		if (this.name[0] != '.')			/*成功返回*/			goto return_base;		/*若长度为1*/		if (this.len == 1)			/*设nd->last_type为LAST_DOT*/			nd->last_type = LAST_DOT;		/*若前两个字母均为'.'*/		else if (this.len == 2 && this.name[1] == '.')			/*设nd->last_type为LAST_DOTDOT*/			nd->last_type = LAST_DOTDOT;/*成功返回*/return_base:		return 0;		/*释放资源并返回出错信息*/out_dput:		/*释放dentry资源*/		dput(dentry);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -