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

📄 namei.c

📁 linux的文件系统的部分代码的详细注释
💻 C
📖 第 1 页 / 共 5 页
字号:
	int count = 0;	/*取出低两位操作标志*/	acc_mode = ACC_MODE(flag);	/*若不需创建文件*/	if (!(flag & O_CREAT)) {		/*在进程目录文件表搜索已有文件,并把结果拷贝到该nameidata结构*/		if (path_init(pathname, lookup_flags(flag), nd))			error = path_walk(pathname, nd);		/*若查找不成功则返回错误信息*/		if (error)			return error;		/*获取文件dentry结构*/		dentry = nd->dentry;		/*执行打开操作,更新inode*/		goto ok;	}	/*进程文件表中搜索该文件,若不存在则创建*/	if (path_init(pathname, LOOKUP_PARENT, nd))		error = path_walk(pathname, nd);	/*查找不成功返回错误信息*/	if (error)		return error;	/*检测查找结果是否是目录文件,是则返回*/	error = -EISDIR;	if (nd->last_type != LAST_NORM || nd->last.name[nd->last.len])		/*跳转到返回程序段*/		goto exit;	/*获取文件相关目录数据返回到dentry*/	down(&dir->d_inode->i_sem);	/*获得散列值并查找对应dentry结构*/	dentry = lookup_hash(&nd->last, nd->dentry);do_last:	/*如果dentry是一个错误值则返回*/	error = PTR_ERR(dentry);	if (IS_ERR(dentry)) {		/*处理信号量*/		up(&dir->d_inode->i_sem);		/*返回*/		goto exit;	}	/* *若与目录项相关的索引节点不存在则创建*/	if (!dentry->d_inode) {		/*VFS系统新建一个inode*/		error = vfs_create(dir->d_inode, dentry,				   mode & ~current->fs->umask);		/*处理信号量*/		up(&dir->d_inode->i_sem);		dput(nd->dentry);		nd->dentry = dentry;		/*创建不成功返回*/		if (error)			goto exit;		/* 无需检查写权限*/		acc_mode = 0;		flag &= ~O_TRUNC;		/*执行打开操作*/		goto ok;	}	/*	 * *若与目录项相关的索引节点已存在	 */	up(&dir->d_inode->i_sem); 	/*如果指定了O_EXCL和O_CREAT,文件存在时,出错*/	error = -EEXIST;	if (flag & O_EXCL)		goto exit_dput;	/*检测文件是否是链接文件*/	if (d_mountpoint(dentry)) {		error = -ELOOP;		/*如果指定不遍历链接文件则返回*/		if (flag & O_NOFOLLOW)			goto exit_dput;		/*检测dentry挂载点*/		while (__follow_down(&nd->mnt,&dentry) && d_mountpoint(dentry));	}	error = -ENOENT;	/*inode不存在则返回*/	if (!dentry->d_inode)		goto exit_dput;	/*允许遍历链接文件则找到链接文件对应的文件*/	if (dentry->d_inode->i_op && dentry->d_inode->i_op->follow_link)		goto do_link;	/*将处理后的dentry复制到nd结构中,并判断其是否是目录,是则返回错误*/	dput(nd->dentry);	nd->dentry = dentry;	error = -EISDIR;	if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode))		goto exit;ok:	/*打开文件返回处理结果代码*/	error = -ENOENT;	inode = dentry->d_inode;	/*inode为空则返回*/	if (!inode)		goto exit;	error = -ELOOP;	/*若是连接文件则返回*/	if (S_ISLNK(inode->i_mode))		goto exit;		error = -EISDIR;	/*是目录且仅有写权限则返回*/	if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))		goto exit;	/*检则该索引节点是否有acc_mode标志*/	error = permission(inode,acc_mode);	if (error)		goto exit;	/* 如果是FIFO文件,则不允许truncate*/	if (S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {	    	flag &= ~O_TRUNC;	} 	/*如果是设备文件则不允许truncate*/	else if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {		error = -EACCES;		/*设备文件却允许truncate则要返回错误信息*/		if (nd->mnt->mnt_flags & MNT_NODEV)			goto exit;		flag &= ~O_TRUNC;	} else {		error = -EROFS;		/*如果flag标识和inode权限冲突,则返回错误*/		if (IS_RDONLY(inode) && (flag & 2))			goto exit;	}	/*	 * 如果inode只允许append方式写入,则不允许truncate和非append写入方式。	 */	error = -EPERM;	if (IS_APPEND(inode)) {		if  ((flag & FMODE_WRITE) && !(flag & O_APPEND))			goto exit;		if (flag & O_TRUNC)			goto exit;	}	/*	 * 若有其它进程使用该文件,则返回	 */	error = get_lease(inode, flag);	if (error)		goto exit;	/*若可以truncate*/	if (flag & O_TRUNC) {		/*获取一次inode写操作权限*/		error = get_write_access(inode);		if (error)			goto exit;		/*锁定inode*/		error = locks_verify_locked(inode);		if (!error) {			/*对inode执行配额初始化*/			DQUOT_INIT(inode);			/*truncate dentry*/			error = do_truncate(dentry, 0);		}		/*释放当前写操作权限*/		put_write_access(inode);		if (error)			goto exit;	} else		/*如果有写标识,则对inode执行配额初始化*/		if (flag & FMODE_WRITE)			DQUOT_INIT(inode);	return 0;exit_dput:	/*释放dentry*/	dput(dentry);exit:	/*释放nameidata结构*/	path_release(nd);	return error;do_link:	error = -ELOOP;	/*不允许遍历链接文件则返回错误*/	if (flag & O_NOFOLLOW)		goto exit_dput;	/*	 * This is subtle. Instead of calling do_follow_link() we do the	 * thing by hands. The reason is that this way we have zero link_count	 * and path_walk() (called from ->follow_link) honoring LOOKUP_PARENT.	 *link_count为0	 * After that we have the parent and last component, i.e.	 * we are in the same situation as after the first path_walk().	 * Well, almost - if the last component is normal we get its copy	 * stored in nd->last.name and we will have to putname() it when we	 * are done. Procfs-like symlinks just set LAST_BIND.	 */	 /*更新上次访问文件的时间*/	UPDATE_ATIME(dentry->d_inode);	/*调用操作函数集中follow_link函数查找指定的文件*/	error = dentry->d_inode->i_op->follow_link(dentry, nd);	/*释放目录项对象*/	dput(dentry);	/*若查找有错则返回错误类型*/	if (error)		return error;	/*若查找成功*/	if (nd->last_type == LAST_BIND) {		dentry = nd->dentry;		goto ok;	}	error = -EISDIR;	/*若未成功找到目标文件则返回*/	if (nd->last_type != LAST_NORM)		goto exit;	/*查找到的是目录则返回*/	if (nd->last.name[nd->last.len]) {		/*释放内存中nd->last.name*/		putname(nd->last.name);		goto exit;	}	error = -ELOOP;	/*若链接过多则释放资源返回*/	if (count++==32) {		/*释放内存中nd->last.name*/		putname(nd->last.name);		goto exit;	}	dir = nd->dentry;	/*获取文件相关目录数据返回到dentry*/	down(&dir->d_inode->i_sem);	dentry = lookup_hash(&nd->last, nd->dentry);	putname(nd->last.name);	goto do_last;}/*在给定目录下查找指定类型文件所对应的目录项对象未找到则创建  *查找或创建所得返回dentry地址*/static struct dentry *lookup_create(struct nameidata *nd, int is_dir){	struct dentry *dentry;	/*处理信号量*/	down(&nd->dentry->d_inode->i_sem);	dentry = ERR_PTR(-EEXIST);	/*未找到目标文件则fail返回*/	if (nd->last_type != LAST_NORM)		goto fail;	/*生成散列值,并据该散列值查找相应的dentry结构,若未找到则创建该dentry*/	dentry = lookup_hash(&nd->last, nd->dentry);	/*如果出错则返回*/	if (IS_ERR(dentry))		goto fail;	/*找到文件类型与传入参数所指类型不匹配则释放dentry*/	if (!is_dir && nd->last.name[nd->last.len] && !dentry->d_inode)		goto enoent;	return dentry;enoent:	/*释放dentry资源*/	dput(dentry);	/*返回值置入错误信息*/	dentry = ERR_PTR(-ENOENT);fail:	return dentry;}/*在给定目录下,为与目录项相关的特殊文件创建一个新的磁盘索节点结点*/int vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev){	int error = -EPERM;	/*处理信号量*/	down(&dir->i_zombie);	/*若是字符设备或块设备或不可建立设备文件节点则跳转到返回段*/	if ((S_ISCHR(mode) || S_ISBLK(mode)) && !capable(CAP_MKNOD))		goto exit_lock;	/*若不可以创建则跳转到返回段*/	error = may_create(dir, dentry);	if (error)		goto exit_lock;	error = -EPERM;	/*索引操作中无mknod操作则跳转到返回段*/	if (!dir->i_op || !dir->i_op->mknod)		goto exit_lock;	/*磁盘配额*/	DQUOT_INIT(dir);	/*上锁*/	lock_kernel();	/*在dir目录下,为与目录项相关的特殊文件创建一个新的磁盘索引节点*/	error = dir->i_op->mknod(dir, dentry, mode, dev);	/*解锁*/	unlock_kernel();exit_lock:	/*处理信号量*/	up(&dir->i_zombie);	/*文件dir中的i_dnotify_mask定义为DN_RENAME重命名*/	if (!error)		inode_dir_notify(dir, DN_CREATE);	return error;}/*为特殊文件创建一个新的磁盘索引节点 */asmlinkage long sys_mknod(const char * filename, int mode, dev_t dev){	int error = 0;	char * tmp;	struct dentry * dentry;	struct nameidata nd;	/*若是目录文件则返回错误信息*/	if (S_ISDIR(mode))		return -EPERM;	/*分配内存空间*/	tmp = getname(filename);	/*分配内存空间有错则返回*/	if (IS_ERR(tmp))		return PTR_ERR(tmp);	/*在内存中找到或建立代表着目标文件或目录dentry结构和inode结构由old_nd反回搜索结果*/	if (path_init(tmp, LOOKUP_PARENT, &nd))		error = path_walk(tmp, &nd);	if (error)		goto out;	/*查找指定类型文件所对应的目录项对象*/	dentry = lookup_create(&nd, 0);	error = PTR_ERR(dentry);	/*重设文件类型*/	mode &= ~current->fs->umask;	/*若查找dentry成功*/	if (!IS_ERR(dentry)) {		switch (mode & S_IFMT) {		case 0: case S_IFREG:			error = vfs_create(nd.dentry->d_inode,dentry,mode);			break;		case S_IFCHR: case S_IFBLK: case S_IFIFO: case S_IFSOCK:			error = vfs_mknod(nd.dentry->d_inode,dentry,mode,dev);			break;		case S_IFDIR:			error = -EPERM;			break;		default:			error = -EINVAL;		}		dput(dentry);	}	up(&nd.dentry->d_inode->i_sem);	path_release(&nd);out:	putname(tmp);	return error;}/*在某个目录下,为与目录项对象相关的目录创建一个新的索引节点  *创建成功则返回0,不成功则返回错误信息*/int vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode){	int error;	/*处理信号量*/	down(&dir->i_zombie);	/*判断是否可以创建节点*/	error = may_create(dir, dentry);	/*若有错,则跳转到返回段*/	if (error)		goto exit_lock;	error = -EPERM;	/*若索引节点操作中无mkdir操作则跳转到返回段*/	if (!dir->i_op || !dir->i_op->mkdir)		goto exit_lock;	/*磁盘配额*/	DQUOT_INIT(dir);	/*????*/	mode &= (S_IRWXUGO|S_ISVTX);	/*上锁*/	lock_kernel();	/*在当前给定目录下,为与目录项对象相关的符号链创建一个新的索引节点*/	error = dir->i_op->mkdir(dir, dentry, mode);	/*解锁*/	unlock_kernel();exit_lock:	/*处理信号量*/	up(&dir->i_zombie);	/*文件dir中的i_dnotify_mask定义为DN_RENAME重命名*/	if (!error)		inode_dir_notify(dir, DN_CREATE);	return error;}/*为相关的目录创建一个新的索引节点*/asmlinkage long sys_mkdir(const char * pathname, int mode){	int error = 0;	char * tmp;	/*分配内存空间*/	tmp = getname(pathname);	error = PTR_ERR(tmp);	/*分配空间成功*/	if (!IS_ERR(tmp)) {		struct dentry *dentry;		struct nameidata nd;		/*在内存中找到或建立代表着目标文件或目录dentry结构和inode结构由old_nd反回搜索结果*/		if (path_init(tmp, LOOKUP_PARENT, &nd))			error = path_walk(tmp, &nd);		if (error)			goto out;		/*查找指定类型文件所对应的目录项对象*/		dentry = lookup_create(&nd, 1);		error = PTR_ERR(dentry);		if (!IS_ERR(dentry)) {			/*在某个目录下,为与目录对象相关的目录创建一个新的索引节点*/			error = vfs_mkdir(nd.dentry->d_inode, dentry,					  mode & ~current->fs->umask);			/*释放dentry资源*/			dput(dentry);		}		/*处理信号量*/		up(&nd.dentry->d_inode->i_sem);		/*释放资源*/		path_release(&nd);out:		putname(tmp);	}	return error;}/*若当前dentry有两个用户时则可以提前抛弃它,  *撤消其哈希值使得cache lookup无法查找到该子目录  *底层文件系统通过这样的语句调用该函数  *if (!d_unhashed(dentry)) *		return -EBUSY;  * We try to drop the dentry early: we should have * a usage count of 2 if we're the only user of this * dentry, and if that is true (possibly after pruning * the dcache), then we drop the dentry now. * * A low-level filesystem can, if it choses, legally * do a

⌨️ 快捷键说明

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