RPC代碼位于net/sunrpc/
幾個概念
以下信息可以在/sys/kernel/debug/sunrpc中查看
xprt (transport)
struct rpc_xprt
描述,代表一個連接(可以是TCP,UDP和RDMA)瘩缆。由xprt_create_transport
創(chuàng)建闹啦。
rpc client
struct rpc_clnt
描述焙压,代表一個client handle。由rpc_create
創(chuàng)建,它會創(chuàng)建transport括荡,并發(fā)送ping,判斷是否對方支持這個RPC
rpc message
struct rpc_message
描述综看,代表一個rpc message脾拆,在創(chuàng)建task時候需要描述rpc message馒索,里面包括傳輸?shù)膮?shù),返回的參數(shù)地址名船,發(fā)生/接收時候用到編碼/解碼函數(shù)等绰上。
rpc task
struct rpc_task
描述,代表一個task,內(nèi)部是一個有限狀態(tài)機渠驼。
RPC 除調(diào)度之外的其它接口
- rpc_create //返回rpc_clnt
- xprt_create_transport //返回rpc_xprt,代表一個TCP連接
- rpc_create_xprt //根據(jù)rpc_xprt,返回一個rpc_clnt
RPC task數(shù)據(jù)結(jié)構(gòu)
每個Task(struct rpc_task
)就是一個有限狀態(tài)機蜈块,狀態(tài)機運行完畢表示這個task運行完畢。
RPC Task 調(diào)度函數(shù)
- rpc_execute //運行狀態(tài)機
- 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設(shè)置為call_start
rpc_execute()中谋梭,如果task需要prepare,狀態(tài)機從rpc_prepare_task()開始運行,否則從call_start開始信峻。
NFS Client構(gòu)造RPC request
NFS Client是sunrpc重要客戶,NFS的RPC請求本質(zhì)上都是構(gòu)造struct rpc_task
瓮床,然后調(diào)用rpc_run_task完成的盹舞。
調(diào)用rpc_call_sync()
=>rpc_call_sync() => rpc_run_task() => rpc_execute()
參見nfs4_proc_exchange_id
的實現(xiàn)
調(diào)用rpc_call_async()
=>rpc_call_async() => rpc_run_task() => rpc_execute()
參見nfs4_proc_async_renew
的實現(xiàn)
直接調(diào)用rpc_run_task()
參見nfs41_proc_reclaim_complete
的實現(xiàn)。
需要注意的是隘庄,rpc_task狀態(tài)機還提供了一些callback踢步,允許在運行之前和之后會被調(diào)用。例如:
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 狀態(tài)機 狀態(tài)轉(zhuǎn)移
__rpc_execute
是RPC的處理函數(shù)丑掺,本質(zhì)上是一個有限狀態(tài)機FSM
获印。如果是同步RPC,由rpc_execute
調(diào)用街州。如果是異步RPC,由rpc_execute
插入到work queue中調(diào)用兼丰。
__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:調(diào)用__rpc_execute運行rpc task狀態(tài)機匣掸。同步RPC調(diào)用運行在調(diào)用者的運行上下文,異步RPC在這個work queue執(zhí)行__rpc_execute氮双。
- xprtiod_workqueue:處理網(wǎng)絡(luò)收發(fā)(在Linux 4.4中還沒有這個)
- nfsiod_workqueue:rpc task使用結(jié)束后碰酝,需要調(diào)用rpc_free_task進行回收】艚叮回收可以同步砰粹,也可以異步。異步回收時在這個work queue中造挽。這是nfs的RPC請求時提供的碱璃。
統(tǒng)計參數(shù)
/proc/net/rpc/