RPC代码位于net/sunrpc/
几个概念
以下信息可以在/sys/kernel/debug/sunrpc中查看
xprt (transport)
struct rpc_xprt
描述,代表一个连接(可以是TCP,UDP和RDMA)。由xprt_create_transport
创建。
rpc client
struct rpc_clnt
描述,代表一个client handle。由rpc_create
创建,它会创建transport,并发送ping,判断是否对方支持这个RPC
rpc message
struct rpc_message
描述,代表一个rpc message,在创建task时候需要描述rpc message,里面包括传输的参数,返回的参数地址,发生/接收时候用到编码/解码函数等。
rpc task
struct rpc_task
描述,代表一个task,内部是一个有限状态机。
RPC 除调度之外的其它接口
- rpc_create //返回rpc_clnt
- xprt_create_transport //返回rpc_xprt,代表一个TCP连接
- rpc_create_xprt //根据rpc_xprt,返回一个rpc_clnt
RPC task数据结构
每个Task(struct rpc_task
)就是一个有限状态机,状态机运行完毕表示这个task运行完毕。
RPC Task 调度函数
- rpc_execute //运行状态机
- rpc_run_task //用
rpc_task_setup
描述task,对rpc_execute的封装 - rpc_call_sync //用
rpc_message
描述task,对rpc_run_task的封装 - rpc_call_async //用
rpc_message
描述task,对rpc_run_task的封装 - rpc_call_start //将task->tk_action设置为call_start
rpc_execute()中,如果task需要prepare,状态机从rpc_prepare_task()开始运行,否则从call_start开始。
NFS Client构造RPC request
NFS Client是sunrpc重要客户,NFS的RPC请求本质上都是构造struct rpc_task
,然后调用rpc_run_task完成的。
调用rpc_call_sync()
=>rpc_call_sync() => rpc_run_task() => rpc_execute()
参见nfs4_proc_exchange_id
的实现
调用rpc_call_async()
=>rpc_call_async() => rpc_run_task() => rpc_execute()
参见nfs4_proc_async_renew
的实现
直接调用rpc_run_task()
参见nfs41_proc_reclaim_complete
的实现。
需要注意的是,rpc_task状态机还提供了一些callback,允许在运行之前和之后会被调用。例如:
static const struct rpc_call_ops nfs4_reclaim_complete_call_ops = {
.rpc_call_prepare = nfs4_reclaim_complete_prepare,
.rpc_call_done = nfs4_reclaim_complete_done,
.rpc_release = nfs4_free_reclaim_complete_data,
};
RPC Task 状态机 状态转移
__rpc_execute
是RPC的处理函数,本质上是一个有限状态机FSM
。如果是同步RPC,由rpc_execute
调用。如果是异步RPC,由rpc_execute
插入到work queue中调用。
__rpc_execute(struct rpc_task *task)
{
for(;;)
{
task->tk_callback(); //如call_start,call_reserve等。在这里修改tk_callback
}
}
rpc_call_start() => call_start => call_reserve => call_refresh => ... => call_connect => 等等
- call_start //0. Initial state
- call_reserve //1. Reserve an RPC call slot
- call_refresh //2. Bind and/or refresh the credentials
- rpc_xdr_encode //3. Encode arguments of an RPC call
- call_bind //4. Get the server port number if not yet set
- call_transmit //5. Transmit the RPC request, and wait for reply
- call_status //6. Sort out the RPC call status
- call_decode //7. Decode the RPC reply
work queue
sun rpc里边会使用三个workqueue,分别是rpciod_workqueue,xprtiod_workqueue,nfsiod_workqueue。
- rpciod_workqueue:调用__rpc_execute运行rpc task状态机。同步RPC调用运行在调用者的运行上下文,异步RPC在这个work queue执行__rpc_execute。
- xprtiod_workqueue:处理网络收发(在Linux 4.4中还没有这个)
- nfsiod_workqueue:rpc task使用结束后,需要调用rpc_free_task进行回收。回收可以同步,也可以异步。异步回收时在这个work queue中。这是nfs的RPC请求时提供的。
统计参数
/proc/net/rpc/
网友评论