EXT4文件系统学习(17)路径定位

根据一个路径定位到一个文件的inode和数据块,这个过程看起来简单,但代码比较复杂。路径定位的过程就是依次从dentry对象的子节点匹配下一级目录,直到定位到最终的节点。

路径定位

进程的fs->root和fs->pwd这2个dentry对象分别指向进程的根目录和当前目录,以根目录/开头时就从fs->root作为起点,否则表示相对路径就从fs->pwd开始。

比较重要的几个结构体:qstr,path,nameidata

include/linux/dcache.h

struct qstr {
	union {
		struct {
			HASH_LEN_DECLARE;
		};
		u64 hash_len;
	};
	const unsigned char *name;
};

qstr表示路径字符串的项目,在路径定位过程中,以/bin/bash为例,qstr对象的name先指向内核解析出的bin字符串,len为3,后面的以此类推。

static int link_path_walk(const char *name, struct nameidata *nd)
{
	while (*name=='/')
		name++;
	if (!*name)
		return 0;
	for(;;) {
		u64 hash_len;
		int type;

		err = may_lookup(nd);
 		if (err)
			break;

		hash_len = hash_name(name);

继续看nameidata的定义

enum { MAX_NESTED_LINKS = 8 };

struct nameidata {
	struct path	path;
	struct qstr	last;
	struct path	root;
	struct inode	*inode; /* path.dentry.d_inode */
	unsigned int	flags;
	unsigned	seq, m_seq;
	int		last_type;
	unsigned	depth;
	char *saved_names[MAX_NESTED_LINKS + 1];
};

 指针数组saved_names指向每一级别的符号链接,最大为8,这是为了避免定位符号链接陷入死循环,结合depth使用,depth表示符号链接的深度,最大为8.

struct path {
	struct vfsmount *mnt;
	struct dentry *dentry;
};

现在来看具体定位路径的过程do_path_lookup函数:

static int do_path_lookup(int dfd, const char *name,
				unsigned int flags, struct nameidata *nd)
{
	struct filename filename = { .name = name };

	return filename_lookup(dfd, &filename, flags, nd);
}

中间的路径字符解析代码比较繁琐暂不分析了,上面代码都是在内存中查找和搜索,如果找不到就读取磁盘数据查找,接下来看具体文件系统的lookup实现:

const struct inode_operations ext4_dir_inode_operations = {
	.lookup		= ext4_lookup,
static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
{
	struct inode *inode;
	struct ext4_dir_entry_2 *de;
	struct buffer_head *bh;

	if (dentry->d_name.len > EXT4_NAME_LEN)
		return ERR_PTR(-ENAMETOOLONG);

	bh = ext4_find_entry(dir, &dentry->d_name, &de, NULL);

通过文件名dentry->d_name读取磁盘上面的信息获取到具体的direntry数据装入到磁盘direntry结构体ext4_dir_entry_2中,具体就是里面有个大循环进行搜索。

	if (bh) {
		__u32 ino = le32_to_cpu(de->inode);
		brelse(bh);

		inode = ext4_iget(dir->i_sb, ino);
	}
	return d_splice_alias(inode, dentry);

获取到inode号后,通过函数ext4_iget获取到VFS中的inode结构,最后通过d_splice_alias把inode加入到direntry树中返回。

 

猜你喜欢

转载自blog.csdn.net/TSZ0000/article/details/88578886