之前我们讲过vfs虚拟文件系统的lookup文件查找的实现,知道当内核的缓存没有找到的时候,就会调用到inode_operations结构体的lookup函数来实现,我们今天以ext2文件系统为例,来讲解一下对应文件系统的lookup函数的实现。
首先ext2的inode_operation结构体定义在ext2/namei.c,定义如下
可以看出来lookup函数是ext2_lookup,这个函数也定义在ext2/namei.c,定义如下
然后我们看一下ext2_inode_by_name函数,这个函数定义在fs/ext2/dir.c,定义如下
我们继续看ext2_find_entry函数,ext2_find_entry函数定义在fs/ext2/dir.c,定义如下
首先ext2的inode_operation结构体定义在ext2/namei.c,定义如下
const struct inode_operations ext2_dir_inode_operations = {
.create = ext2_create,
.lookup = ext2_lookup,
.link = ext2_link,
.unlink = ext2_unlink,
.symlink = ext2_symlink,
.mkdir = ext2_mkdir,
.rmdir = ext2_rmdir,
.mknod = ext2_mknod,
.rename = ext2_rename,
#ifdef CONFIG_EXT2_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext2_listxattr,
.removexattr = generic_removexattr,
#endif
.setattr = ext2_setattr,
.permission = ext2_permission,
};
可以看出来lookup函数是ext2_lookup,这个函数也定义在ext2/namei.c,定义如下
static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
{
struct inode * inode;
ino_t ino;
/*如果目录项的名字长度太长会返回错误*/
if (dentry->d_name.len > EXT2_NAME_LEN)
return ERR_PTR(-ENAMETOOLONG);
/*核心的操作,ext2文件系统通过文件名寻找inode,返回inode的编号*/
ino = ext2_inode_by_name(dir, dentry);
inode = NULL;
if (ino) {
/*根据索引节点号来创造inode结构*/
inode = iget(dir->i_sb, ino);
if (!inode)
return ERR_PTR(-EACCES);
}
/*说明出现错误,inode和dentry断开连接,处理*/
return d_splice_alias(inode, dentry);
}
然后我们看一下ext2_inode_by_name函数,这个函数定义在fs/ext2/dir.c,定义如下
ino_t ext2_inode_by_name(struct inode * dir, struct dentry *dentry)
{
ino_t res = 0;
struct ext2_dir_entry_2 * de;
struct page *page;
/*关键操作*/
de = ext2_find_entry (dir, dentry, &page);
if (de) {
/*如果返回正确,得到inode号码,然后释放page*/
res = le32_to_cpu(de->inode);
ext2_put_page(page);
}
return res;
}
我们继续看ext2_find_entry函数,ext2_find_entry函数定义在fs/ext2/dir.c,定义如下
struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir,
struct dentry *dentry, struct page ** res_page)
{
/*父目录的名字和长度*/
const char *name = dentry->d_name.name;
int namelen = dentry->d_name.len;
/*指向下一个目录项的指针,以时间换空间的做法*/
unsigned reclen = EXT2_DIR_REC_LEN(namelen);
unsigned long start, n;
/*返回这个inode在ext2文件系统占用的page数目*/
unsigned long npages = dir_pages(dir);
struct page *page = NULL;
struct ext2_inode_info *ei = EXT2_I(dir);
ext2_dirent * de;
/*如果这个目录是空的,就直接返回*/
if (npages == 0)
goto out;
/* OFFSET_CACHE */
*res_page