前面的文章中我们讲解了一个RPC请求的处理流程。一个RPC请求的基本处理过程包含三个步骤:(1)解析RPC报文头;(2)验证用户身份;(3)处理这个请求。前两个步骤我们已经讲过了,这篇文章详细讲讲第三个步骤的具体处理过程。为了简单起见,这里挑选了一个简单的请求REMOVE。
一个NFS请求的处理过程分成三个步骤
1.解码RPC请求报文净荷中的NFS数据。
2.处理NFS请求。
3.将处理结果组装到RPC应答消息的净荷中。
前面的文章中我们提到过,一个RPC例程的数据结构是
struct svc_procedure {
// 这是RPC请求的处理函数
svc_procfunc pc_func; /* process the request */
// 这是RPC请求的解码函数,RPC报文的内容是pc_func的参数,
// 这个函数负责解析这些内容
kxdrproc_t pc_decode; /* XDR decode args */
// 这是RPC请求的编码函数,服务器端需要将pc_func的处理结果封装到
// RPC应答报文中,这就是封装函数
kxdrproc_t pc_encode; /* XDR encode result */
// 这是释放内存的一个函数,因为pc_func可能需要分配额外的内存
kxdrproc_t pc_release; /* XDR free result */
// 这是RPC请求报文中数据的长度
unsigned int pc_argsize; /* argument struct size */
// 这是RPC应答报文中数据的长度
unsigned int pc_ressize; /* result struct size */
// 这是这个例程的调用次数,就是一个统计量
unsigned int pc_count; /* call count */
// 这是缓存类型,NFS中某些请求可以缓存处理结果。当再次接收到相同的请求后,
// 就不处理了,直接将缓存中的数据返回给客户端就可以了。
unsigned int pc_cachetype; /* cache info (NFS) */
// 这是调整RPC应答消息缓存的一个数据量
unsigned int pc_xdrressize; /* maximum size of XDR reply */
};
对于REMOVE操作来说,这个数据结构如下
.pc_func = (svc_procfunc) nfsd3_proc_remove,
.pc_decode = (kxdrproc_t) nfs3svc_decode_diropargs,
.pc_encode = (kxdrproc_t) nfs3svc_encode_wccstatres,
.pc_release = (kxdrproc_t) nfs3svc_release_fhandle,
.pc_argsize = sizeof(struct nfsd3_diropargs),
.pc_ressize = sizeof(struct nfsd3_wccstatres),
.pc_cachetype = RC_REPLBUFF,
.pc_xdrressize = ST+WC,
步骤1:解码REMOVE请求参数
REMOVE请求的参数保存在RPC请求报文的净荷中。根据RFC1813的规定,REMOVE请求包含两个参数:父目录的文件句柄和要删除文件的名称。下一篇文件中我们会详细讲解文件句柄,这里只需要知道服务器端可以根据文件句柄查找到父目录就可以了。REMOVE请求的解码函数如下:
int nfs3svc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p,
struct nfsd3_diropargs *args)
{
if (!(p = decode_fh(p, &args->fh)) // 解码父目录的文件句柄
|| !(p = decode_filename(p, &args->name, &args->len))) /