接前一篇文章:Linux内核有什么之块设备驱动有什么第五回 —— 邂逅的三个文件系统之二:实际文件系统(2)
本文内容参考:
34 | 块设备(上):如何建立代理商销售模式?-趣谈Linux操作系统-极客时间
特此致谢!
上回书以F2FS文件系统为例,开始分析块设备邂逅的第二个文件系统:实际文件系统。本回继续沿着源码流程进行分析。
上一回的流程为:
struct file_system_type f2fs_fs_type --->
f2fs_fs_type->mount --->
f2fs_mount --->
mount_bdev --->
lookup_bdev
上一回就讲到这个lookup_bdev函数。其在block/bdev.c中,代码如下:
/**
* lookup_bdev() - Look up a struct block_device by name.
* @pathname: Name of the block device in the filesystem.
* @dev: Pointer to the block device's dev_t, if found.
*
* Lookup the block device's dev_t at @pathname in the current
* namespace if possible and return it in @dev.
*
* Context: May sleep.
* Return: 0 if succeeded, negative errno otherwise.
*/
int lookup_bdev(const char *pathname, dev_t *dev)
{
struct inode *inode;
struct path path;
int error;
if (!pathname || !*pathname)
return -EINVAL;
error = kern_path(pathname, LOOKUP_FOLLOW, &path);
if (error)
return error;
inode = d_backing_inode(path.dentry);
error = -ENOTBLK;
if (!S_ISBLK(inode->i_mode))
goto out_path_put;
error = -EACCES;
if (!may_open_dev(&path))
goto out_path_put;
*dev = inode->i_rdev;
error = 0;
out_path_put:
path_put(&path);
return error;
}
根据函数注释,lookup_bdev函数的作用是按名称查找block_device结构。其实这个注释应该是对于老版本来说的,新版本代码中下边的把那一句描述更准确:在当前命名空间中,查找pathname所对应的块设备的dev_t,并在第二个参数dev中返回(如果能够找到)。其第一个参数const char *pathname是文件系统中块设备的名字,也就是设备的文件名(/dev/xxx);第二个参数dev_t *dev是找到时,指向块设备的dev_t的指针。注意,这个文件是在devtmpfs文件系统中的。
(1)lookup_bdev函数首先调用kern_path函数。kern_path函数可以在这个文件系统(devtmpfs)里面,一直找到设备的文件名对应的dentry。代码片段如下:
error = kern_path(pathname, LOOKUP_FOLLOW, &path);
if (error)
return error;
kern_path函数在fs/namei.c中,代码如下:
int kern_path(const char *name, unsigned int flags, struct path *path)
{
struct filename *filename = getname_kernel(name);
int ret = filename_lookup(AT_FDCWD, filename, flags, path, NULL);
putname(filename);
return ret;
}
EXPORT_SYMBOL(kern_path);
(2)lookup_bdev函数接下来调用d_backing_inode函数。d_backing_inode函数会根据kern_path函数得到的path.dentry获得对应的inode。代码片段如下:
inode = d_backing_inode(path.dentry);
d_backing_inode函数在include/linux/dcache.h中,代码如下:
/**
* d_backing_inode - Get upper or lower inode we should be using
* @upper: The upper layer
*
* This is the helper that should be used to get at the inode that will be used
* if this dentry were to be opened as a file. The inode may be on the upper
* dentry or it may be on a lower dentry pinned by the upper.
*
* Normal filesystems should not use this to access their own inodes.
*/
static inline struct inode *d_backing_inode(const struct dentry *upper)
{
struct inode *inode = upper->d_inode;
return inode;
}
注意,这个path.dentry所对应的inode就是前文书讲到的init_special_inode函数中生成的那个特殊inode。当时笔者说埋一个伏笔,就在这出现(用到)了。
(3)得到根据pathname找到的对应块设备的dev_t,并赋给第二个参数dev返回(如果能够找到)。代码片段如下:
*dev = inode->i_rdev;
这个inode->i_rdev正是上边在init_special_inode函数中赋值的。
inode->i_rdev = rdev;
也就是说,lookup_bdev函数返回的指向块设备的dev_t的指针,指向的正是上边的这个rdev,即调用init_special_inode函数时传给第三个参数dev_t rdev所对应的实参。
至此,lookup_bdev函数就解析完了。欲知后事如何,且看下回分解。
标签:函数,error,文件系统,dev,之块,Linux,path,bdev,inode From: https://blog.csdn.net/phmatthaus/article/details/136817904