今天我们看下read过程。从系统调用,到读取文件内容是怎么样的过程。
接下来看下如何根据fd获取files
接下来看下__fcheck_files函数逻辑:
从上面逻辑可以看到fcheck_files函数核心就是检查fd是否超出max_fds
根据fd找到file之后,接下来就是从file读取数据。即ret = vfs_read(f.file, buf, count,ppos);
针对xfs,会调用fs/xfs/xfs_file.c里的xfs_file_read_iter()函数 generic_file_read_iter()函数定义在mm/filemap.c文件中 direct_IO()是个函数指针,针对不同文件系统会调用对应的函数,本文以xfs为例,但xfs没有实现direct_IO()逻辑,因此会调用fs/block_dev.c文件里的direct_IO(),即:
遍历获取缓冲区数据,并按照BIO_MAX_PAGES(256)个page数提交给devicedriver layer,即submit_bio()函数,接下来看下submit_bio()函数逻辑:
generic_make_request()函数主要通过
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() 其中mfn就是blk_mq_make_request()。
接下来看下blk_mq_make_request()函数: blk_mq_get_request()函数核心部分是tag = blk_mq_get_tag(data);
blk_mq_get_tag()函数核心部分: 下图表示blk_mq_make_request()函数的核心调用逻辑
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,但能够被发送出去之前,需要有地方入写到这里面来。