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

📄 namei.c

📁 linux的文件系统的部分代码的详细注释
💻 C
📖 第 1 页 / 共 5 页
字号:
		break;	}	/*释放资源*/	path_release(nd);/*返回错误信息*/return_err:	return err;}/*查找相应的dentry结构*/int path_walk(const char * name, struct nameidata *nd){	/*置当前文件链为空0*/	current->total_link_count = 0;	/*调用link_path_walk*/	return link_path_walk(name, nd);}/* SMP-safe *//*将nameidata指针指向相应的dentry 和vfsmount*/static int __emul_lookup_dentry(const char *name, struct nameidata *nd){	/*调用path_walk()若不能找到相应的dentry则返回0*/	if (path_walk(name, nd))		return 0;		       /*如果通过altroot寻找没有出错,	  *nd中保留了经过path_walk()的数据	  *但当前nd中没有d_inode,从另一个root入口重新找入*/	if (!nd->dentry->d_inode || S_ISDIR(nd->dentry->d_inode->i_mode)) {		/*建立一个新的nameidata*/		struct nameidata nd_root;		nd_root.last_type = LAST_ROOT;		nd_root.flags = nd->flags;		/*将当前进程所用文件系统的根目录信息		  *赋给nameidata的相应项*/		read_lock(&current->fs->lock);		nd_root.mnt = mntget(current->fs->rootmnt);		nd_root.dentry = dget(current->fs->root);		read_unlock(&current->fs->lock);		/*******/		if (path_walk(name, &nd_root))			return 1;				/*查找成功nd中各项值重新赋值*/		if (nd_root.dentry->d_inode) {			path_release(nd);			nd->dentry = nd_root.dentry;			nd->mnt = nd_root.mnt;			nd->last = nd_root.last;			return 1;		}		path_release(&nd_root);	}	return 1;}/*设置替换根目录*/void set_fs_altroot(void){	/*获取替换根目录*/	char *emul = __emul_prefix();	/*新建一个nameidata结构*/	struct nameidata nd;	/*mnt指向替换目录的vfsmount的变量	  *oldmnt指向原替换目录的vfsmount的变量*/	struct vfsmount *mnt = NULL, *oldmnt;	/*dentry指向替换目录dentry的变量	  *olddentry指向原替换目录dentry的变量*/	struct dentry *dentry = NULL, *olddentry;	if (emul) {				/*读加锁*/		read_lock(&current->fs->lock);		/*nameidata结构的mnt、dentry指向当前根目录的对应项*/		nd.mnt = mntget(current->fs->rootmnt);		nd.dentry = dget(current->fs->root);		/*读解锁*/		read_unlock(&current->fs->lock);		/*设置nameidata结构查找方式标记*/		nd.flags = LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_POSITIVE;				/*查找要替换的路径*/		if (path_walk(emul,&nd) == 0) {			/*找到则更改mnt指向替换目录的vfsmount的变量*/			mnt = nd.mnt;			/*找到则更改dentry指向替换目录dentry的变量*/			dentry = nd.dentry;		}	}	/*写加锁实现互斥*/	write_lock(&current->fs->lock);	/*记录原来的替换根目录指针*/	oldmnt = current->fs->altrootmnt;	olddentry = current->fs->altroot;	/*重新设置替换根目录的altrootmnt指向对应的vfsmount*/	current->fs->altrootmnt = mnt;	/*重新设置替换根目录的altroot指向对应的dentry*/	current->fs->altroot = dentry;	/*写解锁*/	write_unlock(&current->fs->lock);	/*释放资源*/	if (olddentry) {		dput(olddentry);		mntput(oldmnt);	}}/* 给定的文件在根录下,对其nameidata结构初始化 */static inline intwalk_init_root(const char *name, struct nameidata *nd){	/*上锁*/	read_lock(&current->fs->lock);		/*判断当前的文件系统是否存在altroot*/	if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {		/*当前文件系系统的altrootmnt、altroot		  *赋给nameidata的相应项*/		nd->mnt = mntget(current->fs->altrootmnt);		nd->dentry = dget(current->fs->altroot);		/*解锁*/		read_unlock(&current->fs->lock);				/*调用__emul_lookup_dentry(name,nd)看能否找到相应的dentry*/		if (__emul_lookup_dentry(name,nd))			/*找到返回0*/			return 0;		read_lock(&current->fs->lock);	}	/*若当前文件系统不存在altroot	  *将当前进程文件系统的rootmnt、root	  *赋给nameidata的相应项*/	nd->mnt = mntget(current->fs->rootmnt);	nd->dentry = dget(current->fs->root);		/*解锁*/	read_unlock(&current->fs->lock);	return 1;}/* 主要实现对于nameidata数据结构的一些初始化工作*/int path_init(const char *name, unsigned int flags, struct nameidata *nd){	/*文件名尾部指向上一级的类型	  *LAST_ROOT是以“/”指向上一级	  *其它类型还有LAST_NORM,  LAST_DOT, LAST_DOTDOT, LAST_BIND*/	nd->last_type = LAST_ROOT; 		/*设置查找方式标记*/	nd->flags = flags;	/*处理在根目录下的文件*/	if (*name=='/')		return walk_init_root(name,nd);	/*上锁*/	read_lock(&current->fs->lock);		/*得到当前进程文件系统的vsmount*/	nd->mnt = mntget(current->fs->pwdmnt);	/*得到当前进程文件系统的dentry*/	nd->dentry = dget(current->fs->pwd);	/*解锁*/	read_unlock(&current->fs->lock);	return 1;}/*生成散列值,并据该散列值查找相应的dentry结构,若未找到则创建该dentry*/struct dentry * lookup_hash(struct qstr *name, struct dentry * base){	/*要返回的dentry结构*/	struct dentry * dentry;	struct inode *inode;	/*记录调用函数返回值的变量*/	int err;	inode = base->d_inode;	/*判断该结点是否有执行权限*/	err = permission(inode, MAY_EXEC);	dentry = ERR_PTR(err);	/*不可执行则返回*/	if (err)		goto out;	/*	 * 判断文件系统是否存在具体的散列函数	 */	if (base->d_op && base->d_op->d_hash) {		/*生成一个散列值,结果存在name结构中*/		err = base->d_op->d_hash(base, name);		dentry = ERR_PTR(err);		/*散列值生成不成功则返回*/		if (err < 0)			goto out;	}	/*高速缓存中查找指定的dentry*/	dentry = cached_lookup(base, name, 0);	/*高速缓存中未找到*/	if (!dentry) {		/*根据指定入口分配一个新的dentry*/		struct dentry *new = d_alloc(base, name);		dentry = ERR_PTR(-ENOMEM);		/*若分配不成功则返回*/		if (!new)			goto out;		/*上锁*/		lock_kernel();		/*查找new中所指索引结点所在目录*/		dentry = inode->i_op->lookup(inode, new);		/*解锁*/		unlock_kernel();		/*若查找结果为空则返回new*/		if (!dentry)			dentry = new;		/*查找不空释放new资源*/		else			dput(new);	}out:	return dentry;}/* 给定路径和该路径节点名称,查找该节点所对应的目录项对象  *查找则返回找到的dentry地址*/struct dentry * lookup_one_len(const char * name, struct dentry * base, int len){	unsigned long hash;	struct qstr this;	unsigned int c;	this.name = name;	this.len = len;	/*若len为0则返回错误信息*/	if (!len)		goto access;	/*将散列值清零*/	hash = init_name_hash();	/*对一层目录名做散列转化*/	while (len--) {		c = *(const unsigned char *)name++;		if (c == '/' || c == '\0')			goto access;		/*执行散列转化函数*/		hash = partial_name_hash(c, hash);	}	/*获得要查找节点的散列值*/	this.hash = end_name_hash(hash);	/*查找dentry*/	return lookup_hash(&this, base);access:	/*返回错误信息(命令拒绝执行)*/	return ERR_PTR(-EACCES);}/* *通过调用path_init()、path_walk(), *根据给定的文件路径名 *在内存中找到或建立代表着目标文件或目录的dentry结构和inode结构。 */int __user_walk(const char *name, unsigned flags, struct nameidata *nd){	char *tmp;	int err;	/*在系统空间中分配一个页面	  *并从用户空间把文件名复制到这个页面上*/	tmp = getname(name);	/*获得返回结果*/	err = PTR_ERR(tmp);	if (!IS_ERR(tmp)) {		err = 0;		/*nameidata数据结构的一些初始化*/		if (path_init(tmp, flags, nd))			/*查找相应的dentry结构*/			err = path_walk(tmp, nd);		/*因为动态分布,释放申请的页面*/		putname(tmp);	}	return err;}/* * It's inline, so penalty for filesystems that don't use sticky bit is * minimal. */static inline int check_sticky(struct inode *dir, struct inode *inode){	/*检查文件的粘滞位,只有粘滞为只能被文件的所有者和目录的所有者或root修改*/	if (!(dir->i_mode & S_ISVTX))		return 0;	/*若当前文件系统的用户号和文件的用户号相同*/	if (inode->i_uid == current->fsuid)		return 0;	/*若当前文件系统的用户号和目录的用户号相同*/	if (dir->i_uid == current->fsuid)		return 0;	return !capable(CAP_FOWNER);}/* *	Check whether we can remove a link victim from directory dir, check *  whether the type of victim is right. *检测在指定路径下是否可以删除与victim相关的inode *dir目录必需是可执行可写的,且是非append-only,非immutable *victim目录项对象所指索引结点非append-only,非immutable *victim目录项对象必需与要删除文件的属性一致 *victim目录项非根目录 *若可删除返回0,不可删除返回其它错误信息 *  1. We can't do it if dir is read-only (done in permission()) *  2. We should have write and exec permissions on dir *  3. We can't remove anything from append-only dir *  4. We can't do anything with immutable dir (done in permission()) *  5. If the sticky bit on dir is set we should either *	a. be owner of dir, or *	b. be owner of victim, or *	c. have CAP_FOWNER capability *  6. If the victim is append-only or immutable we can't do antyhing with *     links pointing to it. *  7. If we were asked to remove a directory and victim isn't one - ENOTDIR. *  8. If we were asked to remove a non-directory and victim isn't one - EISDIR. *  9. We can't remove a root or mountpoint. */static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir){	int error;	/*若索引节点与目录项所指索引结点不对应则返回错误信息*/	if (!victim->d_inode || victim->d_parent->d_inode != dir)		return -ENOENT;	/*判断是否有MAY_WRITE、MAY_EXEC权限*/	error = permission(dir,MAY_WRITE | MAY_EXEC);	/*无MAY_WRITE、MAY_EXEC权限则返回错误信息*/	if (error)		return error;	/*若是append-only则返回错误信息*/	if (IS_APPEND(dir))		return -EPERM;	/*若victim目录项所指索引节点是append-only或是永久的则返回错误信息*/	if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||	    IS_IMMUTABLE(victim->d_inode))		return -EPERM;	/*要删除目录*/	if (isdir) {		/*victim所指索引结点不是目录则返回错误信息*/		if (!S_ISDIR(victim->d_inode->i_mode))			return -ENOTDIR;		/*victim所指索引结点是根目录则返回错误信息*/		if (IS_ROOT(victim))			return -EBUSY;	} 	/*要删除的不是目录而victim所指索引结点是目录也返回错误信息*/	else if (S_ISDIR(victim->d_inode->i_mode))		return -EISDIR;	/*以上条件都符合返回可删除的信息0*/	return 0;}/* *检测在指定路径下是否可以新建一个与dentry目录项相关的inode *以下三种情况下不允许新建: *1、给定dentry的d_inode已经有效 *2、如果给定目录是只读的 *3、如果给定目录是永久的 *给定目录访问权限必是既可MAY_WRITE又可MAY_EXEC *返回值0表示可以新建,其它表错误信息 */static inline int may_create(struct inode *dir, struct dentry *child) {	/*若该dentry已经指向一个inode结构则返回错误信息*/	if (child->d_inode)		return -EEXIST;	/*若该目录是只读则返回错误信息*/	if (IS_DEADDIR(dir))		return -ENOENT;	/*判断给定目录的访问权是否既MAY_WRITE又MAY_EXEC*/	return permission(dir,MAY_WRITE | MAY_EXEC);}/* 根据参数f构造一个查找标识符retval,该标志为LOOKUP_FOLLOW和LOOKUP_DIRECTORY的组合 */static inline int lookup_flags(unsigned int f){	/*初始化查找标识符为LOOKUP_FOLLOW(顺次查找)*/	unsigned long retval = LOOKUP_FOLLOW;	/*若f 中定义了O_NOFOLLOW(不跟随查找)则去掉retval中LOOKUP_FOLLOW*/	if (f & O_NOFOLLOW)		retval &= ~LOOKUP_FOLLOW;	/*若f中定义了O_CREAT|O_EXCL表示需要创建,则去掉retval中LOOKUP_FOLLOW*/	if ((f & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))		retval &= ~LOOKUP_FOLLOW;	/*若f为O_DIRECTORY表示为目录,则增加LOOKUP_DIRECTORY表示查找目标必须是目录*/	if (f & O_DIRECTORY)		retval |= LOOKUP_DIRECTORY;	/*返回查找标识符*/	return retval;}/*根据给定信息在VFS系统新建一个inode*/int vfs_create(struct inode *dir, struct dentry *dentry, int mode){	int error;		mode &= S_IALLUGO;	mode |= S_IFREG;	/*处理信号量*/	down(&dir->i_zombie);	/*判断是否可以在dir目录下新建一个与dentry有关的索引结点*/	error = may_create(dir, dentry);	/*若有错,则返回*/	if (error)		goto exit_lock;	error = -EACCES;	/* shouldn't it be ENOSYS? */	/*若当前目录的i_op所指函数集中无create函数,则返回*/	if (!dir->i_op || !dir->i_op->create)		goto exit_lock;	/*磁盘配额*/	DQUOT_INIT(dir);	/*加锁*/	lock_kernel();	/*在dir目录下为与dentry目录项相关的正规文件创建一个新的磁盘索引节点*/	error = dir->i_op->create(dir, dentry, mode);	/*解锁*/	unlock_kernel();exit_lock:	/*处理信号量*/	up(&dir->i_zombie);	if (!error)		inode_dir_notify(dir, DN_CREATE);	return error;}/*主要执行文件操作inode部分的打开工作 */int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd){	int acc_mode, error = 0;	struct inode *inode;	/*要打开文件的dentry*/	struct dentry *dentry;	/*父目录的dentry*/	struct dentry *dir;

⌨️ 快捷键说明

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