linux内核VFS之read

linux内核VFS之read

Posted by lwk on September 4, 2020

今天我们看下read过程。从系统调用,到读取文件内容是怎么样的过程。

image image 接下来看下如何根据fd获取files

image image image image image image image 接下来看下__fcheck_files函数逻辑: image

image image image 从上面逻辑可以看到fcheck_files函数核心就是检查fd是否超出max_fds

根据fd找到file之后,接下来就是从file读取数据。即ret = vfs_read(f.file, buf, count,ppos); image image

image

image 针对xfs,会调用fs/xfs/xfs_file.c里的xfs_file_read_iter()函数 image image image generic_file_read_iter()函数定义在mm/filemap.c文件中 image direct_IO()是个函数指针,针对不同文件系统会调用对应的函数,本文以xfs为例,但xfs没有实现direct_IO()逻辑,因此会调用fs/block_dev.c文件里的direct_IO(),即: image image

image

遍历获取缓冲区数据,并按照BIO_MAX_PAGES(256)个page数提交给devicedriver layer,即submit_bio()函数,接下来看下submit_bio()函数逻辑: image

generic_make_request()函数主要通过 image

generic_make_request()函数回调q->make_request_fn()函数,make_request_fn()在块设备初始化时调用blk_mq_init_queue()设置回调函数,函数定义在在block/blk-mq.c文件,在块设备初始化时设置给队列发送消息的回调函数。

blk_mq_init_queue()-> blk_mq_init_allocated_queue()->blk_queue_make_request() image 其中mfn就是blk_mq_make_request()。

接下来看下blk_mq_make_request()函数: image blk_mq_get_request()函数核心部分是tag = blk_mq_get_tag(data);

blk_mq_get_tag()函数核心部分: image 下图表示blk_mq_make_request()函数的核心调用逻辑

image deadline_next_request完成的功能本质上就是从hctx->queue->elevator->elevator_data->next_rq中取出一个元素。

这儿从blk_mq_run_hw_queue函数出发,到最终的scsi_dispatch_cmd函数的调用,发现消息以scsi_cmnd的形式发送到了底层驱动。

这些消息是从dd->next_rq[data_dir]中获取的,这儿的dd是deadline_data,但能够被发送出去之前,需要有地方入写到这里面来。