1.前言
本文主要介绍f2fs读取流程
2.调用流程
vfs_read
file->f_op->read(do_sync_read)
generic_file_aio_read
do_generic_file_read
mapping->a_ops->readpage
read系统调用会调用到vfs_read,进而调用到file->f_op->read,这个read回调是在创建文件时初始化为inode->i_fops->read, 对于f2fs就是do_sync_read,它会进一步调用generic_file_aio_read,对于非直读的情况则会调用mapping->a_ops->readpage回调,它也是在创建文件时通过f2fs_create进行初始化的,mapping->a_ops初始化为f2fs_dblock_aops,因此mapping->a_ops->readpage初始化为f2fs_read_data_page
3.f2fs_read_data_page
f2fs_read_data_page
mpage_readpage(page, get_data_block_ro)
do_mpage_readpage(bio, page, 1, &last_block_in_bio,&map_bh...)
mpage_bio_submit(READ, bio)
do_mpage_readpage会执行read page操作,其中的page是在do_generic_file_read时以文件的读取位置为索引分配的page,它位于file->inode的address_space。bio为要提交给block层的连续逻辑地址的IO, map_bh为buffer_head,用于联系page和bio。这个函数最终会构造bio来提交给block层,为了构建bio,必须要建立文件逻辑块与磁盘逻辑块的关系,因此就要调用到f2fs的get_data_block_ro。
之后通过mpage_bio_submit来提交返回的bio
get_data_block_ro
-
get_data_block_ro中参数iblock可理解为文件的逻辑偏移,bh_result为映射文件逻辑块和磁盘块的buffer_haed, 通过 pgofs = (pgoff_t)(iblock >> (PAGE_CACHE_SHIFT - blkbits));获取到逻辑块偏移地址,保存在pgofs 。
-
以pgofs 偏移地址作为dnode page的索引,调用get_dnode_of_data(&dn, pgofs, RDONLY_NODE),获取到dnode page中以pgofs为索引的block addr,这个地址将保存在dn.data_blkaddr
-
通过一个for循环从pgofs索引开始,遍历临近的逻辑块,看是否有连续的磁盘块与之对应,以实现read ahead操作。
-
for循环结束后通过map_bh(bh_result, inode->i_sb, dn.data_blkaddr)记录buffer_result的起始磁盘块号为dn.data_blkaddr,它就是对应文件逻辑偏移pgofs
bh_result->b_size = (i << blkbits)用以修改bh_result->b_size,包含了read ahead的连续的磁盘块的大小,单位是字节。