diff options
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r-- | net/sunrpc/xprtsock.c | 121 |
1 files changed, 95 insertions, 26 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 441bd53f5eca..9b62923a9c06 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -125,6 +125,47 @@ static inline void xs_pktdump(char *msg, u32 *packet, unsigned int count) | |||
125 | } | 125 | } |
126 | #endif | 126 | #endif |
127 | 127 | ||
128 | static void xs_format_peer_addresses(struct rpc_xprt *xprt) | ||
129 | { | ||
130 | struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr; | ||
131 | char *buf; | ||
132 | |||
133 | buf = kzalloc(20, GFP_KERNEL); | ||
134 | if (buf) { | ||
135 | snprintf(buf, 20, "%u.%u.%u.%u", | ||
136 | NIPQUAD(addr->sin_addr.s_addr)); | ||
137 | } | ||
138 | xprt->address_strings[RPC_DISPLAY_ADDR] = buf; | ||
139 | |||
140 | buf = kzalloc(8, GFP_KERNEL); | ||
141 | if (buf) { | ||
142 | snprintf(buf, 8, "%u", | ||
143 | ntohs(addr->sin_port)); | ||
144 | } | ||
145 | xprt->address_strings[RPC_DISPLAY_PORT] = buf; | ||
146 | |||
147 | if (xprt->prot == IPPROTO_UDP) | ||
148 | xprt->address_strings[RPC_DISPLAY_PROTO] = "udp"; | ||
149 | else | ||
150 | xprt->address_strings[RPC_DISPLAY_PROTO] = "tcp"; | ||
151 | |||
152 | buf = kzalloc(48, GFP_KERNEL); | ||
153 | if (buf) { | ||
154 | snprintf(buf, 48, "addr=%u.%u.%u.%u port=%u proto=%s", | ||
155 | NIPQUAD(addr->sin_addr.s_addr), | ||
156 | ntohs(addr->sin_port), | ||
157 | xprt->prot == IPPROTO_UDP ? "udp" : "tcp"); | ||
158 | } | ||
159 | xprt->address_strings[RPC_DISPLAY_ALL] = buf; | ||
160 | } | ||
161 | |||
162 | static void xs_free_peer_addresses(struct rpc_xprt *xprt) | ||
163 | { | ||
164 | kfree(xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
165 | kfree(xprt->address_strings[RPC_DISPLAY_PORT]); | ||
166 | kfree(xprt->address_strings[RPC_DISPLAY_ALL]); | ||
167 | } | ||
168 | |||
128 | #define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL) | 169 | #define XS_SENDMSG_FLAGS (MSG_DONTWAIT | MSG_NOSIGNAL) |
129 | 170 | ||
130 | static inline int xs_send_head(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, unsigned int len) | 171 | static inline int xs_send_head(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, unsigned int len) |
@@ -174,7 +215,6 @@ static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int a | |||
174 | struct page **ppage = xdr->pages; | 215 | struct page **ppage = xdr->pages; |
175 | unsigned int len, pglen = xdr->page_len; | 216 | unsigned int len, pglen = xdr->page_len; |
176 | int err, ret = 0; | 217 | int err, ret = 0; |
177 | ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int); | ||
178 | 218 | ||
179 | if (unlikely(!sock)) | 219 | if (unlikely(!sock)) |
180 | return -ENOTCONN; | 220 | return -ENOTCONN; |
@@ -207,7 +247,6 @@ static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int a | |||
207 | base &= ~PAGE_CACHE_MASK; | 247 | base &= ~PAGE_CACHE_MASK; |
208 | } | 248 | } |
209 | 249 | ||
210 | sendpage = sock->ops->sendpage ? : sock_no_sendpage; | ||
211 | do { | 250 | do { |
212 | int flags = XS_SENDMSG_FLAGS; | 251 | int flags = XS_SENDMSG_FLAGS; |
213 | 252 | ||
@@ -220,10 +259,7 @@ static inline int xs_sendpages(struct socket *sock, struct sockaddr *addr, int a | |||
220 | if (pglen != len || xdr->tail[0].iov_len != 0) | 259 | if (pglen != len || xdr->tail[0].iov_len != 0) |
221 | flags |= MSG_MORE; | 260 | flags |= MSG_MORE; |
222 | 261 | ||
223 | /* Hmm... We might be dealing with highmem pages */ | 262 | err = kernel_sendpage(sock, *ppage, base, len, flags); |
224 | if (PageHighMem(*ppage)) | ||
225 | sendpage = sock_no_sendpage; | ||
226 | err = sendpage(sock, *ppage, base, len, flags); | ||
227 | if (ret == 0) | 263 | if (ret == 0) |
228 | ret = err; | 264 | ret = err; |
229 | else if (err > 0) | 265 | else if (err > 0) |
@@ -300,7 +336,7 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
300 | 336 | ||
301 | req->rq_xtime = jiffies; | 337 | req->rq_xtime = jiffies; |
302 | status = xs_sendpages(xprt->sock, (struct sockaddr *) &xprt->addr, | 338 | status = xs_sendpages(xprt->sock, (struct sockaddr *) &xprt->addr, |
303 | sizeof(xprt->addr), xdr, req->rq_bytes_sent); | 339 | xprt->addrlen, xdr, req->rq_bytes_sent); |
304 | 340 | ||
305 | dprintk("RPC: xs_udp_send_request(%u) = %d\n", | 341 | dprintk("RPC: xs_udp_send_request(%u) = %d\n", |
306 | xdr->len - req->rq_bytes_sent, status); | 342 | xdr->len - req->rq_bytes_sent, status); |
@@ -490,6 +526,7 @@ static void xs_destroy(struct rpc_xprt *xprt) | |||
490 | 526 | ||
491 | xprt_disconnect(xprt); | 527 | xprt_disconnect(xprt); |
492 | xs_close(xprt); | 528 | xs_close(xprt); |
529 | xs_free_peer_addresses(xprt); | ||
493 | kfree(xprt->slot); | 530 | kfree(xprt->slot); |
494 | } | 531 | } |
495 | 532 | ||
@@ -965,6 +1002,19 @@ static unsigned short xs_get_random_port(void) | |||
965 | } | 1002 | } |
966 | 1003 | ||
967 | /** | 1004 | /** |
1005 | * xs_print_peer_address - format an IPv4 address for printing | ||
1006 | * @xprt: generic transport | ||
1007 | * @format: flags field indicating which parts of the address to render | ||
1008 | */ | ||
1009 | static char *xs_print_peer_address(struct rpc_xprt *xprt, enum rpc_display_format_t format) | ||
1010 | { | ||
1011 | if (xprt->address_strings[format] != NULL) | ||
1012 | return xprt->address_strings[format]; | ||
1013 | else | ||
1014 | return "unprintable"; | ||
1015 | } | ||
1016 | |||
1017 | /** | ||
968 | * xs_set_port - reset the port number in the remote endpoint address | 1018 | * xs_set_port - reset the port number in the remote endpoint address |
969 | * @xprt: generic transport | 1019 | * @xprt: generic transport |
970 | * @port: new port number | 1020 | * @port: new port number |
@@ -972,8 +1022,11 @@ static unsigned short xs_get_random_port(void) | |||
972 | */ | 1022 | */ |
973 | static void xs_set_port(struct rpc_xprt *xprt, unsigned short port) | 1023 | static void xs_set_port(struct rpc_xprt *xprt, unsigned short port) |
974 | { | 1024 | { |
1025 | struct sockaddr_in *sap = (struct sockaddr_in *) &xprt->addr; | ||
1026 | |||
975 | dprintk("RPC: setting port for xprt %p to %u\n", xprt, port); | 1027 | dprintk("RPC: setting port for xprt %p to %u\n", xprt, port); |
976 | xprt->addr.sin_port = htons(port); | 1028 | |
1029 | sap->sin_port = htons(port); | ||
977 | } | 1030 | } |
978 | 1031 | ||
979 | static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock) | 1032 | static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock) |
@@ -986,7 +1039,7 @@ static int xs_bindresvport(struct rpc_xprt *xprt, struct socket *sock) | |||
986 | 1039 | ||
987 | do { | 1040 | do { |
988 | myaddr.sin_port = htons(port); | 1041 | myaddr.sin_port = htons(port); |
989 | err = sock->ops->bind(sock, (struct sockaddr *) &myaddr, | 1042 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, |
990 | sizeof(myaddr)); | 1043 | sizeof(myaddr)); |
991 | if (err == 0) { | 1044 | if (err == 0) { |
992 | xprt->port = port; | 1045 | xprt->port = port; |
@@ -1016,11 +1069,9 @@ static void xs_udp_connect_worker(void *args) | |||
1016 | struct socket *sock = xprt->sock; | 1069 | struct socket *sock = xprt->sock; |
1017 | int err, status = -EIO; | 1070 | int err, status = -EIO; |
1018 | 1071 | ||
1019 | if (xprt->shutdown || xprt->addr.sin_port == 0) | 1072 | if (xprt->shutdown || !xprt_bound(xprt)) |
1020 | goto out; | 1073 | goto out; |
1021 | 1074 | ||
1022 | dprintk("RPC: xs_udp_connect_worker for xprt %p\n", xprt); | ||
1023 | |||
1024 | /* Start by resetting any existing state */ | 1075 | /* Start by resetting any existing state */ |
1025 | xs_close(xprt); | 1076 | xs_close(xprt); |
1026 | 1077 | ||
@@ -1034,6 +1085,9 @@ static void xs_udp_connect_worker(void *args) | |||
1034 | goto out; | 1085 | goto out; |
1035 | } | 1086 | } |
1036 | 1087 | ||
1088 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | ||
1089 | xprt, xs_print_peer_address(xprt, RPC_DISPLAY_ALL)); | ||
1090 | |||
1037 | if (!xprt->inet) { | 1091 | if (!xprt->inet) { |
1038 | struct sock *sk = sock->sk; | 1092 | struct sock *sk = sock->sk; |
1039 | 1093 | ||
@@ -1081,7 +1135,7 @@ static void xs_tcp_reuse_connection(struct rpc_xprt *xprt) | |||
1081 | */ | 1135 | */ |
1082 | memset(&any, 0, sizeof(any)); | 1136 | memset(&any, 0, sizeof(any)); |
1083 | any.sa_family = AF_UNSPEC; | 1137 | any.sa_family = AF_UNSPEC; |
1084 | result = sock->ops->connect(sock, &any, sizeof(any), 0); | 1138 | result = kernel_connect(sock, &any, sizeof(any), 0); |
1085 | if (result) | 1139 | if (result) |
1086 | dprintk("RPC: AF_UNSPEC connect return code %d\n", | 1140 | dprintk("RPC: AF_UNSPEC connect return code %d\n", |
1087 | result); | 1141 | result); |
@@ -1099,11 +1153,9 @@ static void xs_tcp_connect_worker(void *args) | |||
1099 | struct socket *sock = xprt->sock; | 1153 | struct socket *sock = xprt->sock; |
1100 | int err, status = -EIO; | 1154 | int err, status = -EIO; |
1101 | 1155 | ||
1102 | if (xprt->shutdown || xprt->addr.sin_port == 0) | 1156 | if (xprt->shutdown || !xprt_bound(xprt)) |
1103 | goto out; | 1157 | goto out; |
1104 | 1158 | ||
1105 | dprintk("RPC: xs_tcp_connect_worker for xprt %p\n", xprt); | ||
1106 | |||
1107 | if (!xprt->sock) { | 1159 | if (!xprt->sock) { |
1108 | /* start from scratch */ | 1160 | /* start from scratch */ |
1109 | if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { | 1161 | if ((err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock)) < 0) { |
@@ -1119,6 +1171,9 @@ static void xs_tcp_connect_worker(void *args) | |||
1119 | /* "close" the socket, preserving the local port */ | 1171 | /* "close" the socket, preserving the local port */ |
1120 | xs_tcp_reuse_connection(xprt); | 1172 | xs_tcp_reuse_connection(xprt); |
1121 | 1173 | ||
1174 | dprintk("RPC: worker connecting xprt %p to address: %s\n", | ||
1175 | xprt, xs_print_peer_address(xprt, RPC_DISPLAY_ALL)); | ||
1176 | |||
1122 | if (!xprt->inet) { | 1177 | if (!xprt->inet) { |
1123 | struct sock *sk = sock->sk; | 1178 | struct sock *sk = sock->sk; |
1124 | 1179 | ||
@@ -1151,8 +1206,8 @@ static void xs_tcp_connect_worker(void *args) | |||
1151 | /* Tell the socket layer to start connecting... */ | 1206 | /* Tell the socket layer to start connecting... */ |
1152 | xprt->stat.connect_count++; | 1207 | xprt->stat.connect_count++; |
1153 | xprt->stat.connect_start = jiffies; | 1208 | xprt->stat.connect_start = jiffies; |
1154 | status = sock->ops->connect(sock, (struct sockaddr *) &xprt->addr, | 1209 | status = kernel_connect(sock, (struct sockaddr *) &xprt->addr, |
1155 | sizeof(xprt->addr), O_NONBLOCK); | 1210 | xprt->addrlen, O_NONBLOCK); |
1156 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", | 1211 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", |
1157 | xprt, -status, xprt_connected(xprt), sock->sk->sk_state); | 1212 | xprt, -status, xprt_connected(xprt), sock->sk->sk_state); |
1158 | if (status < 0) { | 1213 | if (status < 0) { |
@@ -1260,8 +1315,10 @@ static void xs_tcp_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) | |||
1260 | 1315 | ||
1261 | static struct rpc_xprt_ops xs_udp_ops = { | 1316 | static struct rpc_xprt_ops xs_udp_ops = { |
1262 | .set_buffer_size = xs_udp_set_buffer_size, | 1317 | .set_buffer_size = xs_udp_set_buffer_size, |
1318 | .print_addr = xs_print_peer_address, | ||
1263 | .reserve_xprt = xprt_reserve_xprt_cong, | 1319 | .reserve_xprt = xprt_reserve_xprt_cong, |
1264 | .release_xprt = xprt_release_xprt_cong, | 1320 | .release_xprt = xprt_release_xprt_cong, |
1321 | .rpcbind = rpc_getport, | ||
1265 | .set_port = xs_set_port, | 1322 | .set_port = xs_set_port, |
1266 | .connect = xs_connect, | 1323 | .connect = xs_connect, |
1267 | .buf_alloc = rpc_malloc, | 1324 | .buf_alloc = rpc_malloc, |
@@ -1276,8 +1333,10 @@ static struct rpc_xprt_ops xs_udp_ops = { | |||
1276 | }; | 1333 | }; |
1277 | 1334 | ||
1278 | static struct rpc_xprt_ops xs_tcp_ops = { | 1335 | static struct rpc_xprt_ops xs_tcp_ops = { |
1336 | .print_addr = xs_print_peer_address, | ||
1279 | .reserve_xprt = xprt_reserve_xprt, | 1337 | .reserve_xprt = xprt_reserve_xprt, |
1280 | .release_xprt = xs_tcp_release_xprt, | 1338 | .release_xprt = xs_tcp_release_xprt, |
1339 | .rpcbind = rpc_getport, | ||
1281 | .set_port = xs_set_port, | 1340 | .set_port = xs_set_port, |
1282 | .connect = xs_connect, | 1341 | .connect = xs_connect, |
1283 | .buf_alloc = rpc_malloc, | 1342 | .buf_alloc = rpc_malloc, |
@@ -1298,8 +1357,7 @@ static struct rpc_xprt_ops xs_tcp_ops = { | |||
1298 | int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to) | 1357 | int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to) |
1299 | { | 1358 | { |
1300 | size_t slot_table_size; | 1359 | size_t slot_table_size; |
1301 | 1360 | struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr; | |
1302 | dprintk("RPC: setting up udp-ipv4 transport...\n"); | ||
1303 | 1361 | ||
1304 | xprt->max_reqs = xprt_udp_slot_table_entries; | 1362 | xprt->max_reqs = xprt_udp_slot_table_entries; |
1305 | slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]); | 1363 | slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]); |
@@ -1307,10 +1365,12 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to) | |||
1307 | if (xprt->slot == NULL) | 1365 | if (xprt->slot == NULL) |
1308 | return -ENOMEM; | 1366 | return -ENOMEM; |
1309 | 1367 | ||
1310 | xprt->prot = IPPROTO_UDP; | 1368 | if (ntohs(addr->sin_port != 0)) |
1369 | xprt_set_bound(xprt); | ||
1311 | xprt->port = xs_get_random_port(); | 1370 | xprt->port = xs_get_random_port(); |
1371 | |||
1372 | xprt->prot = IPPROTO_UDP; | ||
1312 | xprt->tsh_size = 0; | 1373 | xprt->tsh_size = 0; |
1313 | xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0; | ||
1314 | /* XXX: header size can vary due to auth type, IPv6, etc. */ | 1374 | /* XXX: header size can vary due to auth type, IPv6, etc. */ |
1315 | xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); | 1375 | xprt->max_payload = (1U << 16) - (MAX_HEADER << 3); |
1316 | 1376 | ||
@@ -1327,6 +1387,10 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to) | |||
1327 | else | 1387 | else |
1328 | xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); | 1388 | xprt_set_timeout(&xprt->timeout, 5, 5 * HZ); |
1329 | 1389 | ||
1390 | xs_format_peer_addresses(xprt); | ||
1391 | dprintk("RPC: set up transport to address %s\n", | ||
1392 | xs_print_peer_address(xprt, RPC_DISPLAY_ALL)); | ||
1393 | |||
1330 | return 0; | 1394 | return 0; |
1331 | } | 1395 | } |
1332 | 1396 | ||
@@ -1339,8 +1403,7 @@ int xs_setup_udp(struct rpc_xprt *xprt, struct rpc_timeout *to) | |||
1339 | int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to) | 1403 | int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to) |
1340 | { | 1404 | { |
1341 | size_t slot_table_size; | 1405 | size_t slot_table_size; |
1342 | 1406 | struct sockaddr_in *addr = (struct sockaddr_in *) &xprt->addr; | |
1343 | dprintk("RPC: setting up tcp-ipv4 transport...\n"); | ||
1344 | 1407 | ||
1345 | xprt->max_reqs = xprt_tcp_slot_table_entries; | 1408 | xprt->max_reqs = xprt_tcp_slot_table_entries; |
1346 | slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]); | 1409 | slot_table_size = xprt->max_reqs * sizeof(xprt->slot[0]); |
@@ -1348,10 +1411,12 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to) | |||
1348 | if (xprt->slot == NULL) | 1411 | if (xprt->slot == NULL) |
1349 | return -ENOMEM; | 1412 | return -ENOMEM; |
1350 | 1413 | ||
1351 | xprt->prot = IPPROTO_TCP; | 1414 | if (ntohs(addr->sin_port) != 0) |
1415 | xprt_set_bound(xprt); | ||
1352 | xprt->port = xs_get_random_port(); | 1416 | xprt->port = xs_get_random_port(); |
1417 | |||
1418 | xprt->prot = IPPROTO_TCP; | ||
1353 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); | 1419 | xprt->tsh_size = sizeof(rpc_fraghdr) / sizeof(u32); |
1354 | xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0; | ||
1355 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; | 1420 | xprt->max_payload = RPC_MAX_FRAGMENT_SIZE; |
1356 | 1421 | ||
1357 | INIT_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt); | 1422 | INIT_WORK(&xprt->connect_worker, xs_tcp_connect_worker, xprt); |
@@ -1367,5 +1432,9 @@ int xs_setup_tcp(struct rpc_xprt *xprt, struct rpc_timeout *to) | |||
1367 | else | 1432 | else |
1368 | xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); | 1433 | xprt_set_timeout(&xprt->timeout, 2, 60 * HZ); |
1369 | 1434 | ||
1435 | xs_format_peer_addresses(xprt); | ||
1436 | dprintk("RPC: set up transport to address %s\n", | ||
1437 | xs_print_peer_address(xprt, RPC_DISPLAY_ALL)); | ||
1438 | |||
1370 | return 0; | 1439 | return 0; |
1371 | } | 1440 | } |