nfsclient 源码笔记

请求分拆

以nfs4 direct_read过程为例,过程中的几个控制结构

  1. dreq,每个io过程的上下文,记录所有io的参数,及中间产生的状态值
  2. nfs_pageio_descriptor, 内核中操作内存都是以page为单位,内存buf最终会转换为多个page组成的list,该类型中,包含list指针,由于dio请求的长度是由系统调用者指定的,所以不可能一次性将数据全部发送,会按照指定的bsize(挂载时指定的每次IO大小进行分拆),每次拆分之后调用一次该描述符的pg_doio(nfs_generic_pg_readpages)接口,这个pg_doio过程也只是再次进行分拆,不会阻塞调用。doio之后,会再次设置nfs_pageio_descriptor的page_count和pg_list,直到将整个dreq中的buff都处理完
  3. nfs_read_header和nfs_pgio_header
    nfs_read_header包含了nfs_pgio_header的结构,并包括nfs_read_data结构,每次调用pg_doio就会生成一个nfs_pgio_header结构,一个nfs_pgio_header初始包括descpg_list中的第一个req,如果指定的bsize(传输大小的限制)
  4. nfs_read_data,如果一个bsize小于一个page的大小,那么需要再次进行拆分,拆分成多个nfs_read_data结构,否则只创建一个nfs_read_data结构,最终使用每个nfs_read_data构建一个rpc_task

rpc的状态机

  1. call_start
  2. call_reserve->xprt_reserve
  3. call_reserveresult
  4. call_refresh->rpcauth_refreshcred
  5. call_refreshresult
  6. call_allocate->xprt->ops->buf_alloc 此处只是申请缓冲区用来存放消息的控制结构,数据部分是使用page指针
  7. call_bind->xprt->ops->rpcbind(task) 此处有标记为检查,已经bound,直接跳过
  8. call_connect->xprt_connect 此处也有标记检查,已经连接直接跳过
  9. call_connect_status 如果执行了xprt_connect操作,那么下一步需要检查连接状态,已经建立连接跳过该步
  10. call_transmit->xprt_prepare_transmit->xprt->ops->reserve_xprt 此处会设置xprt的锁标记->rpc_xdr_encode->xprt_transmit->xprt->ops->send_request ,此处可能会因为发送缓冲区满而无法继续发送,但是会记录已经发送的长度,不会全部从头开始->rpc_sleep_on 在call_transimit,将task在等待队列上,此处不是立即挂起,而是在call_transmi调结束之后,不在调用其他action->call_transmit_status->xprt_end_transmit->xprt_release_write ,此处会释放xprt
  11. call_transmit_status 如果在执行call_transmit过程中出现错误,则task不会挂起,而是执行该步骤
  12. call_status
  13. call_decode

未完待续

声明:转载本博文章须在文章明显处注明作者及附上原文链接,便于读者找到原文的更新版。

你可能感兴趣的:(linux,kernel)