aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2009-05-18 17:47:56 -0400
committerJ. Bruce Fields <bfields@redhat.com>2011-04-07 14:36:40 -0400
commit586c52cc61b5b84c70102208b78269ef5924bf49 (patch)
treec218a2ab64877297dd530c9997e4bbfb6a12577a
parentcc6c2127f2316c2b2ad1e8919b45cde5e03f65aa (diff)
svcrpc: copy cb reply instead of pages
It's much simpler just to copy the cb reply data than to play tricks with pages. Callback replies will typically be very small (at least until we implement cb_getattr, in which case files with very long ACLs could pose a problem), so there's no loss in efficiency. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--net/sunrpc/svcsock.c122
1 files changed, 56 insertions, 66 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 62ff7c5c09c2..40b502b11442 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -981,57 +981,58 @@ static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp)
981 return -EAGAIN; 981 return -EAGAIN;
982} 982}
983 983
984static int svc_process_calldir(struct svc_sock *svsk, struct svc_rqst *rqstp, 984static int receive_cb_reply(struct svc_sock *svsk, struct svc_rqst *rqstp)
985 struct rpc_rqst **reqpp, struct kvec *vec)
986{ 985{
986 struct rpc_xprt *bc_xprt = svsk->sk_xprt.xpt_bc_xprt;
987 struct rpc_rqst *req = NULL; 987 struct rpc_rqst *req = NULL;
988 __be32 *p; 988 struct kvec *src, *dst;
989 __be32 *p = (__be32 *)rqstp->rq_arg.head[0].iov_base;
989 __be32 xid; 990 __be32 xid;
990 __be32 calldir; 991 __be32 calldir;
991 int len;
992
993 len = svc_recvfrom(rqstp, vec, 1, 8);
994 if (len < 0)
995 goto error;
996 992
997 p = (u32 *)rqstp->rq_arg.head[0].iov_base;
998 xid = *p++; 993 xid = *p++;
999 calldir = *p; 994 calldir = *p;
1000 995
1001 if (calldir == 0) { 996 if (bc_xprt)
1002 /* REQUEST is the most common case */ 997 req = xprt_lookup_rqst(bc_xprt, xid);
1003 vec[0] = rqstp->rq_arg.head[0];
1004 } else {
1005 /* REPLY */
1006 struct rpc_xprt *bc_xprt = svsk->sk_xprt.xpt_bc_xprt;
1007
1008 if (bc_xprt)
1009 req = xprt_lookup_rqst(bc_xprt, xid);
1010
1011 if (!req) {
1012 printk(KERN_NOTICE
1013 "%s: Got unrecognized reply: "
1014 "calldir 0x%x xpt_bc_xprt %p xid %08x\n",
1015 __func__, ntohl(calldir),
1016 bc_xprt, xid);
1017 vec[0] = rqstp->rq_arg.head[0];
1018 goto out;
1019 }
1020 998
1021 memcpy(&req->rq_private_buf, &req->rq_rcv_buf, 999 if (!req) {
1022 sizeof(struct xdr_buf)); 1000 printk(KERN_NOTICE
1023 /* copy the xid and call direction */ 1001 "%s: Got unrecognized reply: "
1024 memcpy(req->rq_private_buf.head[0].iov_base, 1002 "calldir 0x%x xpt_bc_xprt %p xid %08x\n",
1025 rqstp->rq_arg.head[0].iov_base, 8); 1003 __func__, ntohl(calldir),
1026 vec[0] = req->rq_private_buf.head[0]; 1004 bc_xprt, xid);
1005 return -EAGAIN;
1027 } 1006 }
1028 out: 1007
1029 vec[0].iov_base += 8; 1008 memcpy(&req->rq_private_buf, &req->rq_rcv_buf, sizeof(struct xdr_buf));
1030 vec[0].iov_len -= 8; 1009 /*
1031 len = svsk->sk_reclen - 8; 1010 * XXX!: cheating for now! Only copying HEAD.
1032 error: 1011 * But we know this is good enough for now (in fact, for any
1033 *reqpp = req; 1012 * callback reply in the forseeable future).
1034 return len; 1013 */
1014 dst = &req->rq_private_buf.head[0];
1015 src = &rqstp->rq_arg.head[0];
1016 if (dst->iov_len < src->iov_len)
1017 return -EAGAIN; /* whatever; just giving up. */
1018 memcpy(dst->iov_base, src->iov_base, src->iov_len);
1019 xprt_complete_rqst(req->rq_task, svsk->sk_reclen);
1020 rqstp->rq_arg.len = 0;
1021 return 0;
1022}
1023
1024static int copy_pages_to_kvecs(struct kvec *vec, struct page **pages, int len)
1025{
1026 int i = 0;
1027 int t = 0;
1028
1029 while (t < len) {
1030 vec[i].iov_base = page_address(pages[i]);
1031 vec[i].iov_len = PAGE_SIZE;
1032 i++;
1033 t += PAGE_SIZE;
1034 }
1035 return i;
1035} 1036}
1036 1037
1037/* 1038/*
@@ -1044,8 +1045,8 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
1044 struct svc_serv *serv = svsk->sk_xprt.xpt_server; 1045 struct svc_serv *serv = svsk->sk_xprt.xpt_server;
1045 int len; 1046 int len;
1046 struct kvec *vec; 1047 struct kvec *vec;
1047 struct rpc_rqst *req = NULL; 1048 __be32 *p;
1048 unsigned int vlen; 1049 __be32 calldir;
1049 int pnum; 1050 int pnum;
1050 1051
1051 dprintk("svc: tcp_recv %p data %d conn %d close %d\n", 1052 dprintk("svc: tcp_recv %p data %d conn %d close %d\n",
@@ -1058,35 +1059,17 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
1058 goto error; 1059 goto error;
1059 1060
1060 vec = rqstp->rq_vec; 1061 vec = rqstp->rq_vec;
1061 vec[0] = rqstp->rq_arg.head[0];
1062 vlen = PAGE_SIZE;
1063 1062
1064 len = svc_process_calldir(svsk, rqstp, &req, vec); 1063 pnum = copy_pages_to_kvecs(&vec[0], &rqstp->rq_pages[0],
1065 if (len < 0) 1064 svsk->sk_reclen);
1066 goto err_again; 1065
1067 vlen -= 8;
1068
1069 pnum = 1;
1070 while (vlen < svsk->sk_reclen - 8) {
1071 vec[pnum].iov_base = (req) ?
1072 page_address(req->rq_private_buf.pages[pnum - 1]) :
1073 page_address(rqstp->rq_pages[pnum]);
1074 vec[pnum].iov_len = PAGE_SIZE;
1075 pnum++;
1076 vlen += PAGE_SIZE;
1077 }
1078 rqstp->rq_respages = &rqstp->rq_pages[pnum]; 1066 rqstp->rq_respages = &rqstp->rq_pages[pnum];
1079 1067
1080 /* Now receive data */ 1068 /* Now receive data */
1081 len = svc_recvfrom(rqstp, vec, pnum, svsk->sk_reclen - 8); 1069 len = svc_recvfrom(rqstp, vec, pnum, svsk->sk_reclen);
1082 if (len < 0) 1070 if (len < 0)
1083 goto err_again; 1071 goto err_again;
1084 1072
1085 if (req) {
1086 xprt_complete_rqst(req->rq_task, svsk->sk_reclen);
1087 rqstp->rq_arg.len = 0;
1088 goto out;
1089 }
1090 dprintk("svc: TCP complete record (%d bytes)\n", svsk->sk_reclen); 1073 dprintk("svc: TCP complete record (%d bytes)\n", svsk->sk_reclen);
1091 rqstp->rq_arg.len = svsk->sk_reclen; 1074 rqstp->rq_arg.len = svsk->sk_reclen;
1092 rqstp->rq_arg.page_base = 0; 1075 rqstp->rq_arg.page_base = 0;
@@ -1099,7 +1082,14 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
1099 rqstp->rq_xprt_ctxt = NULL; 1082 rqstp->rq_xprt_ctxt = NULL;
1100 rqstp->rq_prot = IPPROTO_TCP; 1083 rqstp->rq_prot = IPPROTO_TCP;
1101 1084
1102out: 1085 p = (__be32 *)rqstp->rq_arg.head[0].iov_base;
1086 calldir = p[1];
1087 if (calldir) {
1088 len = receive_cb_reply(svsk, rqstp);
1089 if (len < 0)
1090 goto err_again;
1091 }
1092
1103 /* Reset TCP read info */ 1093 /* Reset TCP read info */
1104 svsk->sk_reclen = 0; 1094 svsk->sk_reclen = 0;
1105 svsk->sk_tcplen = 0; 1095 svsk->sk_tcplen = 0;