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树中返回。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值