diff options
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r-- | net/sunrpc/xprtsock.c | 217 |
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 | ||
274 | static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) | 284 | static 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 | ||
1001 | static inline void xs_tcp_read_request(struct rpc_xprt *xprt, struct xdr_skb_reader *desc) | 1013 | static 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 | |||
1050 | static 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 | ||
1073 | out: | 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 | */ | ||
1134 | static 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 | */ | ||
1170 | static 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 | |||
1209 | static 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 | ||
1220 | static 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 | */ | ||
1231 | static 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 | ||
1080 | static inline void xs_tcp_read_discard(struct sock_xprt *transport, struct xdr_skb_reader *desc) | 1248 | static 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, |