aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/xprtsock.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r--net/sunrpc/xprtsock.c217
1 files changed, 197 insertions, 20 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 6c2d61586551..83c73c4d017a 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -34,6 +34,9 @@
34#include <linux/sunrpc/sched.h> 34#include <linux/sunrpc/sched.h>
35#include <linux/sunrpc/xprtsock.h> 35#include <linux/sunrpc/xprtsock.h>
36#include <linux/file.h> 36#include <linux/file.h>
37#ifdef CONFIG_NFS_V4_1
38#include <linux/sunrpc/bc_xprt.h>
39#endif
37 40
38#include <net/sock.h> 41#include <net/sock.h>
39#include <net/checksum.h> 42#include <net/checksum.h>
@@ -270,6 +273,13 @@ struct sock_xprt {
270#define TCP_RCV_COPY_FRAGHDR (1UL << 1) 273#define TCP_RCV_COPY_FRAGHDR (1UL << 1)
271#define TCP_RCV_COPY_XID (1UL << 2) 274#define TCP_RCV_COPY_XID (1UL << 2)
272#define TCP_RCV_COPY_DATA (1UL << 3) 275#define TCP_RCV_COPY_DATA (1UL << 3)
276#define TCP_RCV_READ_CALLDIR (1UL << 4)
277#define TCP_RCV_COPY_CALLDIR (1UL << 5)
278
279/*
280 * TCP RPC flags
281 */
282#define TCP_RPC_REPLY (1UL << 6)
273 283
274static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) 284static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt)
275{ 285{
@@ -956,7 +966,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea
956 transport->tcp_offset = 0; 966 transport->tcp_offset = 0;
957 967
958 /* Sanity check of the record length */ 968 /* Sanity check of the record length */
959 if (unlikely(transport->tcp_reclen < 4)) { 969 if (unlikely(transport->tcp_reclen < 8)) {
960 dprintk("RPC: invalid TCP record fragment length\n"); 970 dprintk("RPC: invalid TCP record fragment length\n");
961 xprt_force_disconnect(xprt); 971 xprt_force_disconnect(xprt);
962 return; 972 return;
@@ -991,33 +1001,77 @@ static inline void xs_tcp_read_xid(struct sock_xprt *transport, struct xdr_skb_r
991 if (used != len) 1001 if (used != len)
992 return; 1002 return;
993 transport->tcp_flags &= ~TCP_RCV_COPY_XID; 1003 transport->tcp_flags &= ~TCP_RCV_COPY_XID;
994 transport->tcp_flags |= TCP_RCV_COPY_DATA; 1004 transport->tcp_flags |= TCP_RCV_READ_CALLDIR;
995 transport->tcp_copied = 4; 1005 transport->tcp_copied = 4;
996 dprintk("RPC: reading reply for XID %08x\n", 1006 dprintk("RPC: reading %s XID %08x\n",
1007 (transport->tcp_flags & TCP_RPC_REPLY) ? "reply for"
1008 : "request with",
997 ntohl(transport->tcp_xid)); 1009 ntohl(transport->tcp_xid));
998 xs_tcp_check_fraghdr(transport); 1010 xs_tcp_check_fraghdr(transport);
999} 1011}
1000 1012
1001static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_reader *desc) 1013static inline void xs_tcp_read_calldir(struct sock_xprt *transport,
1014 struct xdr_skb_reader *desc)
1002{ 1015{
1003 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); 1016 size_t len, used;
1004 struct rpc_rqst *req; 1017 u32 offset;
1018 __be32 calldir;
1019
1020 /*
1021 * We want transport->tcp_offset to be 8 at the end of this routine
1022 * (4 bytes for the xid and 4 bytes for the call/reply flag).
1023 * When this function is called for the first time,
1024 * transport->tcp_offset is 4 (after having already read the xid).
1025 */
1026 offset = transport->tcp_offset - sizeof(transport->tcp_xid);
1027 len = sizeof(calldir) - offset;
1028 dprintk("RPC: reading CALL/REPLY flag (%Zu bytes)\n", len);
1029 used = xdr_skb_read_bits(desc, &calldir, len);
1030 transport->tcp_offset += used;
1031 if (used != len)
1032 return;
1033 transport->tcp_flags &= ~TCP_RCV_READ_CALLDIR;
1034 transport->tcp_flags |= TCP_RCV_COPY_CALLDIR;
1035 transport->tcp_flags |= TCP_RCV_COPY_DATA;
1036 /*
1037 * We don't yet have the XDR buffer, so we will write the calldir
1038 * out after we get the buffer from the 'struct rpc_rqst'
1039 */
1040 if (ntohl(calldir) == RPC_REPLY)
1041 transport->tcp_flags |= TCP_RPC_REPLY;
1042 else
1043 transport->tcp_flags &= ~TCP_RPC_REPLY;
1044 dprintk("RPC: reading %s CALL/REPLY flag %08x\n",
1045 (transport->tcp_flags & TCP_RPC_REPLY) ?
1046 "reply for" : "request with", calldir);
1047 xs_tcp_check_fraghdr(transport);
1048}
1049
1050static inline void xs_tcp_read_common(struct rpc_xprt *xprt,
1051 struct xdr_skb_reader *desc,
1052 struct rpc_rqst *req)
1053{
1054 struct sock_xprt *transport =
1055 container_of(xprt, struct sock_xprt, xprt);
1005 struct xdr_buf *rcvbuf; 1056 struct xdr_buf *rcvbuf;
1006 size_t len; 1057 size_t len;
1007 ssize_t r; 1058 ssize_t r;
1008 1059
1009 /* Find and lock the request corresponding to this xid */ 1060 rcvbuf = &req->rq_private_buf;
1010 spin_lock(&xprt->transport_lock); 1061
1011 req = xprt_lookup_rqst(xprt, transport->tcp_xid); 1062 if (transport->tcp_flags & TCP_RCV_COPY_CALLDIR) {
1012 if (!req) { 1063 /*
1013 transport->tcp_flags &= ~TCP_RCV_COPY_DATA; 1064 * Save the RPC direction in the XDR buffer
1014 dprintk("RPC: XID %08x request not found!\n", 1065 */
1015 ntohl(transport->tcp_xid)); 1066 __be32 calldir = transport->tcp_flags & TCP_RPC_REPLY ?
1016 spin_unlock(&xprt->transport_lock); 1067 htonl(RPC_REPLY) : 0;
1017 return; 1068
1069 memcpy(rcvbuf->head[0].iov_base + transport->tcp_copied,
1070 &calldir, sizeof(calldir));
1071 transport->tcp_copied += sizeof(calldir);
1072 transport->tcp_flags &= ~TCP_RCV_COPY_CALLDIR;
1018 } 1073 }
1019 1074
1020 rcvbuf = &req->rq_private_buf;
1021 len = desc->count; 1075 len = desc->count;
1022 if (len > transport->tcp_reclen - transport->tcp_offset) { 1076 if (len > transport->tcp_reclen - transport->tcp_offset) {
1023 struct xdr_skb_reader my_desc; 1077 struct xdr_skb_reader my_desc;
@@ -1054,7 +1108,7 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_rea
1054 "tcp_offset = %u, tcp_reclen = %u\n", 1108 "tcp_offset = %u, tcp_reclen = %u\n",
1055 xprt, transport->tcp_copied, 1109 xprt, transport->tcp_copied,
1056 transport->tcp_offset, transport->tcp_reclen); 1110 transport->tcp_offset, transport->tcp_reclen);
1057 goto out; 1111 return;
1058 } 1112 }
1059 1113
1060 dprintk("RPC: XID %08x read %Zd bytes\n", 1114 dprintk("RPC: XID %08x read %Zd bytes\n",
@@ -1070,11 +1124,125 @@ static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_rea
1070 transport->tcp_flags &= ~TCP_RCV_COPY_DATA; 1124 transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
1071 } 1125 }
1072 1126
1073out: 1127 return;
1128}
1129
1130/*
1131 * Finds the request corresponding to the RPC xid and invokes the common
1132 * tcp read code to read the data.
1133 */
1134static inline int xs_tcp_read_reply(struct rpc_xprt *xprt,
1135 struct xdr_skb_reader *desc)
1136{
1137 struct sock_xprt *transport =
1138 container_of(xprt, struct sock_xprt, xprt);
1139 struct rpc_rqst *req;
1140
1141 dprintk("RPC: read reply XID %08x\n", ntohl(transport->tcp_xid));
1142
1143 /* Find and lock the request corresponding to this xid */
1144 spin_lock(&xprt->transport_lock);
1145 req = xprt_lookup_rqst(xprt, transport->tcp_xid);
1146 if (!req) {
1147 dprintk("RPC: XID %08x request not found!\n",
1148 ntohl(transport->tcp_xid));
1149 spin_unlock(&xprt->transport_lock);
1150 return -1;
1151 }
1152
1153 xs_tcp_read_common(xprt, desc, req);
1154
1074 if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) 1155 if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
1075 xprt_complete_rqst(req->rq_task, transport->tcp_copied); 1156 xprt_complete_rqst(req->rq_task, transport->tcp_copied);
1157
1076 spin_unlock(&xprt->transport_lock); 1158 spin_unlock(&xprt->transport_lock);
1077 xs_tcp_check_fraghdr(transport); 1159 return 0;
1160}
1161
1162#if defined(CONFIG_NFS_V4_1)
1163/*
1164 * Obtains an rpc_rqst previously allocated and invokes the common
1165 * tcp read code to read the data. The result is placed in the callback
1166 * queue.
1167 * If we're unable to obtain the rpc_rqst we schedule the closing of the
1168 * connection and return -1.
1169 */
1170static inline int xs_tcp_read_callback(struct rpc_xprt *xprt,
1171 struct xdr_skb_reader *desc)
1172{
1173 struct sock_xprt *transport =
1174 container_of(xprt, struct sock_xprt, xprt);
1175 struct rpc_rqst *req;
1176
1177 req = xprt_alloc_bc_request(xprt);
1178 if (req == NULL) {
1179 printk(KERN_WARNING "Callback slot table overflowed\n");
1180 xprt_force_disconnect(xprt);
1181 return -1;
1182 }
1183
1184 req->rq_xid = transport->tcp_xid;
1185 dprintk("RPC: read callback XID %08x\n", ntohl(req->rq_xid));
1186 xs_tcp_read_common(xprt, desc, req);
1187
1188 if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) {
1189 struct svc_serv *bc_serv = xprt->bc_serv;
1190
1191 /*
1192 * Add callback request to callback list. The callback
1193 * service sleeps on the sv_cb_waitq waiting for new
1194 * requests. Wake it up after adding enqueing the
1195 * request.
1196 */
1197 dprintk("RPC: add callback request to list\n");
1198 spin_lock(&bc_serv->sv_cb_lock);
1199 list_add(&req->rq_bc_list, &bc_serv->sv_cb_list);
1200 spin_unlock(&bc_serv->sv_cb_lock);
1201 wake_up(&bc_serv->sv_cb_waitq);
1202 }
1203
1204 req->rq_private_buf.len = transport->tcp_copied;
1205
1206 return 0;
1207}
1208
1209static inline int _xs_tcp_read_data(struct rpc_xprt *xprt,
1210 struct xdr_skb_reader *desc)
1211{
1212 struct sock_xprt *transport =
1213 container_of(xprt, struct sock_xprt, xprt);
1214
1215 return (transport->tcp_flags & TCP_RPC_REPLY) ?
1216 xs_tcp_read_reply(xprt, desc) :
1217 xs_tcp_read_callback(xprt, desc);
1218}
1219#else
1220static inline int _xs_tcp_read_data(struct rpc_xprt *xprt,
1221 struct xdr_skb_reader *desc)
1222{
1223 return xs_tcp_read_reply(xprt, desc);
1224}
1225#endif /* CONFIG_NFS_V4_1 */
1226
1227/*
1228 * Read data off the transport. This can be either an RPC_CALL or an
1229 * RPC_REPLY. Relay the processing to helper functions.
1230 */
1231static void xs_tcp_read_data(struct rpc_xprt *xprt,
1232 struct xdr_skb_reader *desc)
1233{
1234 struct sock_xprt *transport =
1235 container_of(xprt, struct sock_xprt, xprt);
1236
1237 if (_xs_tcp_read_data(xprt, desc) == 0)
1238 xs_tcp_check_fraghdr(transport);
1239 else {
1240 /*
1241 * The transport_lock protects the request handling.
1242 * There's no need to hold it to update the tcp_flags.
1243 */
1244 transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
1245 }
1078} 1246}
1079 1247
1080static inline void xs_tcp_read_discard(struct sock_xprt *transport, struct xdr_skb_reader *desc) 1248static inline void xs_tcp_read_discard(struct sock_xprt *transport, struct xdr_skb_reader *desc)
@@ -1114,9 +1282,14 @@ static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, uns
1114 xs_tcp_read_xid(transport, &desc); 1282 xs_tcp_read_xid(transport, &desc);
1115 continue; 1283 continue;
1116 } 1284 }
1285 /* Read in the call/reply flag */
1286 if (transport->tcp_flags & TCP_RCV_READ_CALLDIR) {
1287 xs_tcp_read_calldir(transport, &desc);
1288 continue;
1289 }
1117 /* Read in the request data */ 1290 /* Read in the request data */
1118 if (transport->tcp_flags & TCP_RCV_COPY_DATA) { 1291 if (transport->tcp_flags & TCP_RCV_COPY_DATA) {
1119 xs_tcp_read_request(xprt, &desc); 1292 xs_tcp_read_data(xprt, &desc);
1120 continue; 1293 continue;
1121 } 1294 }
1122 /* Skip over any trailing bytes on short reads */ 1295 /* Skip over any trailing bytes on short reads */
@@ -1792,6 +1965,7 @@ static void xs_tcp_setup_socket(struct rpc_xprt *xprt,
1792 */ 1965 */
1793 set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); 1966 set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
1794 xprt_force_disconnect(xprt); 1967 xprt_force_disconnect(xprt);
1968 break;
1795 case -ECONNREFUSED: 1969 case -ECONNREFUSED:
1796 case -ECONNRESET: 1970 case -ECONNRESET:
1797 case -ENETUNREACH: 1971 case -ENETUNREACH:
@@ -2010,6 +2184,9 @@ static struct rpc_xprt_ops xs_tcp_ops = {
2010 .buf_free = rpc_free, 2184 .buf_free = rpc_free,
2011 .send_request = xs_tcp_send_request, 2185 .send_request = xs_tcp_send_request,
2012 .set_retrans_timeout = xprt_set_retrans_timeout_def, 2186 .set_retrans_timeout = xprt_set_retrans_timeout_def,
2187#if defined(CONFIG_NFS_V4_1)
2188 .release_request = bc_release_request,
2189#endif /* CONFIG_NFS_V4_1 */
2013 .close = xs_tcp_close, 2190 .close = xs_tcp_close,
2014 .destroy = xs_destroy, 2191 .destroy = xs_destroy,
2015 .print_stats = xs_tcp_print_stats, 2192 .print_stats = xs_tcp_print_stats,