“块存储:AIO的直接写流程注释”中说到,如果是Direct 写,__generic_file_write_iter将首先调用generic_file_direct_write函数,然后generic_file_direct_write调用块设备的direct_io函数直接写设备,如果direct_io没有将需要写盘的数据写完,就要调用generic_perform_write函数做一次buffer write,即写page cache(块设备也是一种文件,有对应的address_space管理page cache)。下面对generic_perform_write函数的流程做一**释,其主要逻辑分三步:
1,调用块设备的write_begin函数,获取块设备缓存page;
2,调用iov_iter_copy_from_user_atomic将用户要写的用户空间的数据copy到块设备的缓存page中;
3,调用块设备的writer_end函数,在第2步骤已将用户数据copy到块设备的缓存page中,writer_end函数作用就是标记该page为最新、page bh为dirty,等待在合适的时机被刷到设备中。
1,上述generic_perform_write代码中,块设备的writer_begin函数是blkdev_write_begin, 该函数为块设备的缓存准备page:
下图“page,bh与from~to的关系”解释了__block_write_begin_int函数中最后判断要调用ll_rw_block从设备上读取 page中某个块数据的逻辑:
2,generic_perform_write代码中,函数iov_iter_copy_from_user_atomic作用是将用户要写的用户空间的数据copy到块设备的缓存,即page中:
3, generic_perform_write代码中,块设备的writer_end函数是blkdev_write_end,在第2步骤已将用户数据copy到块设备的缓存page中,blkdev_write_end函数作用就是标记该page为最新、page bh为dirty,等待在合适的时机被刷到设备中: