xprtsock.c (f4a2e418bfd03a1f25f515e8a92ecd584d96cfc1) xprtsock.c (44b98efdd0a205bdca2cb63493350d06ff6804b1)
1/*
2 * linux/net/sunrpc/xprtsock.c
3 *
4 * Client-side transport implementation for sockets.
5 *
6 * TCP callback races fixes (C) 1998 Red Hat
7 * TCP send fixes (C) 1998 Red Hat
8 * TCP NFS related read + write fixes

--- 20 unchanged lines hidden (view full) ---

29#include <linux/net.h>
30#include <linux/mm.h>
31#include <linux/udp.h>
32#include <linux/tcp.h>
33#include <linux/sunrpc/clnt.h>
34#include <linux/sunrpc/sched.h>
35#include <linux/sunrpc/xprtsock.h>
36#include <linux/file.h>
1/*
2 * linux/net/sunrpc/xprtsock.c
3 *
4 * Client-side transport implementation for sockets.
5 *
6 * TCP callback races fixes (C) 1998 Red Hat
7 * TCP send fixes (C) 1998 Red Hat
8 * TCP NFS related read + write fixes

--- 20 unchanged lines hidden (view full) ---

29#include <linux/net.h>
30#include <linux/mm.h>
31#include <linux/udp.h>
32#include <linux/tcp.h>
33#include <linux/sunrpc/clnt.h>
34#include <linux/sunrpc/sched.h>
35#include <linux/sunrpc/xprtsock.h>
36#include <linux/file.h>
37#ifdef CONFIG_NFS_V4_1
38#include <linux/sunrpc/bc_xprt.h>
39#endif
37
38#include <net/sock.h>
39#include <net/checksum.h>
40#include <net/udp.h>
41#include <net/tcp.h>
42
43/*
44 * xprtsock tunables

--- 994 unchanged lines hidden (view full) ---

1039 else
1040 transport->tcp_flags &= ~TCP_RPC_REPLY;
1041 dprintk("RPC: reading %s CALL/REPLY flag %08x\n",
1042 (transport->tcp_flags & TCP_RPC_REPLY) ?
1043 "reply for" : "request with", calldir);
1044 xs_tcp_check_fraghdr(transport);
1045}
1046
40
41#include <net/sock.h>
42#include <net/checksum.h>
43#include <net/udp.h>
44#include <net/tcp.h>
45
46/*
47 * xprtsock tunables

--- 994 unchanged lines hidden (view full) ---

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
1047static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_reader *desc)
1050static inline void xs_tcp_read_common(struct rpc_xprt *xprt,
1051 struct xdr_skb_reader *desc,
1052 struct rpc_rqst *req)
1048{
1053{
1049 struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
1050 struct rpc_rqst *req;
1054 struct sock_xprt *transport =
1055 container_of(xprt, struct sock_xprt, xprt);
1051 struct xdr_buf *rcvbuf;
1052 size_t len;
1053 ssize_t r;
1054
1056 struct xdr_buf *rcvbuf;
1057 size_t len;
1058 ssize_t r;
1059
1055 /* Find and lock the request corresponding to this xid */
1056 spin_lock(&xprt->transport_lock);
1057 req = xprt_lookup_rqst(xprt, transport->tcp_xid);
1058 if (!req) {
1059 transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
1060 dprintk("RPC: XID %08x request not found!\n",
1061 ntohl(transport->tcp_xid));
1062 spin_unlock(&xprt->transport_lock);
1063 return;
1064 }
1065
1066 rcvbuf = &req->rq_private_buf;
1067
1068 if (transport->tcp_flags & TCP_RCV_COPY_CALLDIR) {
1069 /*
1070 * Save the RPC direction in the XDR buffer
1071 */
1072 __be32 calldir = transport->tcp_flags & TCP_RPC_REPLY ?
1073 htonl(RPC_REPLY) : 0;

--- 35 unchanged lines hidden (view full) ---

1109 */
1110 transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
1111 dprintk("RPC: XID %08x truncated request\n",
1112 ntohl(transport->tcp_xid));
1113 dprintk("RPC: xprt = %p, tcp_copied = %lu, "
1114 "tcp_offset = %u, tcp_reclen = %u\n",
1115 xprt, transport->tcp_copied,
1116 transport->tcp_offset, transport->tcp_reclen);
1060 rcvbuf = &req->rq_private_buf;
1061
1062 if (transport->tcp_flags & TCP_RCV_COPY_CALLDIR) {
1063 /*
1064 * Save the RPC direction in the XDR buffer
1065 */
1066 __be32 calldir = transport->tcp_flags & TCP_RPC_REPLY ?
1067 htonl(RPC_REPLY) : 0;

--- 35 unchanged lines hidden (view full) ---

1103 */
1104 transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
1105 dprintk("RPC: XID %08x truncated request\n",
1106 ntohl(transport->tcp_xid));
1107 dprintk("RPC: xprt = %p, tcp_copied = %lu, "
1108 "tcp_offset = %u, tcp_reclen = %u\n",
1109 xprt, transport->tcp_copied,
1110 transport->tcp_offset, transport->tcp_reclen);
1117 goto out;
1111 return;
1118 }
1119
1120 dprintk("RPC: XID %08x read %Zd bytes\n",
1121 ntohl(transport->tcp_xid), r);
1122 dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, "
1123 "tcp_reclen = %u\n", xprt, transport->tcp_copied,
1124 transport->tcp_offset, transport->tcp_reclen);
1125
1126 if (transport->tcp_copied == req->rq_private_buf.buflen)
1127 transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
1128 else if (transport->tcp_offset == transport->tcp_reclen) {
1129 if (transport->tcp_flags & TCP_RCV_LAST_FRAG)
1130 transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
1131 }
1132
1112 }
1113
1114 dprintk("RPC: XID %08x read %Zd bytes\n",
1115 ntohl(transport->tcp_xid), r);
1116 dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, "
1117 "tcp_reclen = %u\n", xprt, transport->tcp_copied,
1118 transport->tcp_offset, transport->tcp_reclen);
1119
1120 if (transport->tcp_copied == req->rq_private_buf.buflen)
1121 transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
1122 else if (transport->tcp_offset == transport->tcp_reclen) {
1123 if (transport->tcp_flags & TCP_RCV_LAST_FRAG)
1124 transport->tcp_flags &= ~TCP_RCV_COPY_DATA;
1125 }
1126
1133out:
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
1134 if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
1135 xprt_complete_rqst(req->rq_task, transport->tcp_copied);
1155 if (!(transport->tcp_flags & TCP_RCV_COPY_DATA))
1156 xprt_complete_rqst(req->rq_task, transport->tcp_copied);
1157
1136 spin_unlock(&xprt->transport_lock);
1158 spin_unlock(&xprt->transport_lock);
1137 xs_tcp_check_fraghdr(transport);
1159 return 0;
1138}
1139
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 }
1246}
1247
1140static inline void xs_tcp_read_discard(struct sock_xprt *transport, struct xdr_skb_reader *desc)
1141{
1142 size_t len;
1143
1144 len = transport->tcp_reclen - transport->tcp_offset;
1145 if (len > desc->count)
1146 len = desc->count;
1147 desc->count -= len;

--- 28 unchanged lines hidden (view full) ---

1176 }
1177 /* Read in the call/reply flag */
1178 if (transport->tcp_flags & TCP_RCV_READ_CALLDIR) {
1179 xs_tcp_read_calldir(transport, &desc);
1180 continue;
1181 }
1182 /* Read in the request data */
1183 if (transport->tcp_flags & TCP_RCV_COPY_DATA) {
1248static inline void xs_tcp_read_discard(struct sock_xprt *transport, struct xdr_skb_reader *desc)
1249{
1250 size_t len;
1251
1252 len = transport->tcp_reclen - transport->tcp_offset;
1253 if (len > desc->count)
1254 len = desc->count;
1255 desc->count -= len;

--- 28 unchanged lines hidden (view full) ---

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 }
1290 /* Read in the request data */
1291 if (transport->tcp_flags & TCP_RCV_COPY_DATA) {
1184 xs_tcp_read_request(xprt, &desc);
1292 xs_tcp_read_data(xprt, &desc);
1185 continue;
1186 }
1187 /* Skip over any trailing bytes on short reads */
1188 xs_tcp_read_discard(transport, &desc);
1189 } while (desc.count);
1190 dprintk("RPC: xs_tcp_data_recv done\n");
1191 return len - desc.count;
1192}

--- 1110 unchanged lines hidden ---
1293 continue;
1294 }
1295 /* Skip over any trailing bytes on short reads */
1296 xs_tcp_read_discard(transport, &desc);
1297 } while (desc.count);
1298 dprintk("RPC: xs_tcp_data_recv done\n");
1299 return len - desc.count;
1300}

--- 1110 unchanged lines hidden ---