staging: lustre: align all code properly for LNet core
[deliverable/linux.git] / drivers / staging / lustre / lnet / lnet / lib-socket.c
CommitLineData
d7e09d03
PT
1/*
2 * GPL HEADER START
3 *
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 only,
8 * as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License version 2 for more details (a copy is included
14 * in the LICENSE file that accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License
17 * version 2 along with this program; If not, see
60ecf96e 18 * http://www.gnu.org/licenses/gpl-2.0.html
d7e09d03
PT
19 *
20 * GPL HEADER END
21 */
22/*
23 * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Use is subject to license terms.
25 *
1dc563a6 26 * Copyright (c) 2012, 2015, Intel Corporation.
d7e09d03
PT
27 */
28/*
29 * This file is part of Lustre, http://www.lustre.org/
60ecf96e 30 * Lustre is a trademark of Seagate, Inc.
d7e09d03
PT
31 */
32#define DEBUG_SUBSYSTEM S_LNET
33
d7e09d03
PT
34#include <linux/if.h>
35#include <linux/in.h>
5c2414ef 36#include <linux/net.h>
d7e09d03 37#include <linux/file.h>
5c2414ef 38#include <linux/pagemap.h>
d7e09d03
PT
39/* For sys_open & sys_close */
40#include <linux/syscalls.h>
5c2414ef
JS
41#include <net/sock.h>
42
43#include "../../include/linux/libcfs/libcfs.h"
44#include "../../include/linux/lnet/lib-lnet.h"
45
46static int
47kernel_sock_unlocked_ioctl(struct file *filp, int cmd, unsigned long arg)
48{
49 mm_segment_t oldfs = get_fs();
50 int err;
51
52 set_fs(KERNEL_DS);
53 err = filp->f_op->unlocked_ioctl(filp, cmd, arg);
54 set_fs(oldfs);
55
56 return err;
57}
d7e09d03 58
2a74b9bd 59static int
1ad6a73e 60lnet_sock_ioctl(int cmd, unsigned long arg)
d7e09d03 61{
73092892
JS
62 struct file *sock_filp;
63 struct socket *sock;
64 int rc;
d7e09d03 65
73092892 66 rc = sock_create(PF_INET, SOCK_STREAM, 0, &sock);
d7e09d03 67 if (rc != 0) {
73092892 68 CERROR("Can't create socket: %d\n", rc);
d7e09d03
PT
69 return rc;
70 }
3eeb821e
OD
71
72 sock_filp = sock_alloc_file(sock, 0, NULL);
73 if (IS_ERR(sock_filp)) {
74 sock_release(sock);
75 rc = PTR_ERR(sock_filp);
76 goto out;
77 }
78
5c2414ef 79 rc = kernel_sock_unlocked_ioctl(sock_filp, cmd, arg);
3eeb821e
OD
80
81 fput(sock_filp);
82out:
d7e09d03
PT
83 return rc;
84}
85
86int
73092892 87lnet_ipif_query(char *name, int *up, __u32 *ip, __u32 *mask)
d7e09d03 88{
73092892
JS
89 struct ifreq ifr;
90 int nob;
91 int rc;
92 __u32 val;
d7e09d03
PT
93
94 nob = strnlen(name, IFNAMSIZ);
95 if (nob == IFNAMSIZ) {
96 CERROR("Interface name %s too long\n", name);
97 return -EINVAL;
98 }
99
73092892 100 CLASSERT(sizeof(ifr.ifr_name) >= IFNAMSIZ);
d7e09d03
PT
101
102 strcpy(ifr.ifr_name, name);
1ad6a73e 103 rc = lnet_sock_ioctl(SIOCGIFFLAGS, (unsigned long)&ifr);
d7e09d03
PT
104 if (rc != 0) {
105 CERROR("Can't get flags for interface %s\n", name);
106 return rc;
107 }
108
109 if ((ifr.ifr_flags & IFF_UP) == 0) {
110 CDEBUG(D_NET, "Interface %s down\n", name);
111 *up = 0;
112 *ip = *mask = 0;
113 return 0;
114 }
d7e09d03
PT
115 *up = 1;
116
117 strcpy(ifr.ifr_name, name);
118 ifr.ifr_addr.sa_family = AF_INET;
1ad6a73e 119 rc = lnet_sock_ioctl(SIOCGIFADDR, (unsigned long)&ifr);
d7e09d03
PT
120 if (rc != 0) {
121 CERROR("Can't get IP address for interface %s\n", name);
122 return rc;
123 }
124
125 val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
126 *ip = ntohl(val);
127
128 strcpy(ifr.ifr_name, name);
129 ifr.ifr_addr.sa_family = AF_INET;
1ad6a73e 130 rc = lnet_sock_ioctl(SIOCGIFNETMASK, (unsigned long)&ifr);
d7e09d03
PT
131 if (rc != 0) {
132 CERROR("Can't get netmask for interface %s\n", name);
133 return rc;
134 }
135
136 val = ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr;
137 *mask = ntohl(val);
138
139 return 0;
140}
1ad6a73e 141EXPORT_SYMBOL(lnet_ipif_query);
d7e09d03
PT
142
143int
73092892 144lnet_ipif_enumerate(char ***namesp)
d7e09d03
PT
145{
146 /* Allocate and fill in 'names', returning # interfaces/error */
73092892
JS
147 char **names;
148 int toobig;
149 int nalloc;
150 int nfound;
151 struct ifreq *ifr;
152 struct ifconf ifc;
153 int rc;
154 int nob;
155 int i;
d7e09d03
PT
156
157 nalloc = 16; /* first guess at max interfaces */
158 toobig = 0;
159 for (;;) {
160 if (nalloc * sizeof(*ifr) > PAGE_CACHE_SIZE) {
161 toobig = 1;
162 nalloc = PAGE_CACHE_SIZE/sizeof(*ifr);
163 CWARN("Too many interfaces: only enumerating first %d\n",
164 nalloc);
165 }
166
167 LIBCFS_ALLOC(ifr, nalloc * sizeof(*ifr));
168 if (ifr == NULL) {
73092892
JS
169 CERROR("ENOMEM enumerating up to %d interfaces\n",
170 nalloc);
d7e09d03
PT
171 rc = -ENOMEM;
172 goto out0;
173 }
174
175 ifc.ifc_buf = (char *)ifr;
176 ifc.ifc_len = nalloc * sizeof(*ifr);
177
1ad6a73e 178 rc = lnet_sock_ioctl(SIOCGIFCONF, (unsigned long)&ifc);
d7e09d03 179 if (rc < 0) {
73092892 180 CERROR("Error %d enumerating interfaces\n", rc);
d7e09d03
PT
181 goto out1;
182 }
183
73092892 184 LASSERT(rc == 0);
d7e09d03
PT
185
186 nfound = ifc.ifc_len/sizeof(*ifr);
73092892 187 LASSERT(nfound <= nalloc);
d7e09d03
PT
188
189 if (nfound < nalloc || toobig)
190 break;
191
192 LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
193 nalloc *= 2;
194 }
195
196 if (nfound == 0)
197 goto out1;
198
199 LIBCFS_ALLOC(names, nfound * sizeof(*names));
200 if (names == NULL) {
201 rc = -ENOMEM;
202 goto out1;
203 }
d7e09d03
PT
204
205 for (i = 0; i < nfound; i++) {
73092892 206 nob = strnlen(ifr[i].ifr_name, IFNAMSIZ);
d7e09d03
PT
207 if (nob == IFNAMSIZ) {
208 /* no space for terminating NULL */
209 CERROR("interface name %.*s too long (%d max)\n",
210 nob, ifr[i].ifr_name, IFNAMSIZ);
211 rc = -ENAMETOOLONG;
212 goto out2;
213 }
214
215 LIBCFS_ALLOC(names[i], IFNAMSIZ);
216 if (names[i] == NULL) {
217 rc = -ENOMEM;
218 goto out2;
219 }
220
221 memcpy(names[i], ifr[i].ifr_name, nob);
222 names[i][nob] = 0;
223 }
224
225 *namesp = names;
226 rc = nfound;
227
73092892 228out2:
d7e09d03 229 if (rc < 0)
1ad6a73e 230 lnet_ipif_free_enumeration(names, nfound);
73092892 231out1:
d7e09d03 232 LIBCFS_FREE(ifr, nalloc * sizeof(*ifr));
73092892 233out0:
d7e09d03
PT
234 return rc;
235}
1ad6a73e 236EXPORT_SYMBOL(lnet_ipif_enumerate);
d7e09d03
PT
237
238void
73092892 239lnet_ipif_free_enumeration(char **names, int n)
d7e09d03 240{
73092892 241 int i;
d7e09d03 242
73092892 243 LASSERT(n > 0);
d7e09d03
PT
244
245 for (i = 0; i < n && names[i] != NULL; i++)
246 LIBCFS_FREE(names[i], IFNAMSIZ);
247
248 LIBCFS_FREE(names, n * sizeof(*names));
249}
1ad6a73e 250EXPORT_SYMBOL(lnet_ipif_free_enumeration);
d7e09d03
PT
251
252int
73092892 253lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout)
d7e09d03 254{
73092892
JS
255 int rc;
256 long ticks = timeout * HZ;
257 unsigned long then;
d7e09d03
PT
258 struct timeval tv;
259
73092892 260 LASSERT(nob > 0);
4420cfd3
JS
261 /*
262 * Caller may pass a zero timeout if she thinks the socket buffer is
263 * empty enough to take the whole message immediately
264 */
d7e09d03 265 for (;;) {
480f40de 266 struct kvec iov = {
d7e09d03
PT
267 .iov_base = buffer,
268 .iov_len = nob
269 };
270 struct msghdr msg = {
d7e09d03
PT
271 .msg_flags = (timeout == 0) ? MSG_DONTWAIT : 0
272 };
273
274 if (timeout != 0) {
275 /* Set send timeout to remaining time */
276 tv = (struct timeval) {
277 .tv_sec = ticks / HZ,
278 .tv_usec = ((ticks % HZ) * 1000000) / HZ
279 };
80db2734 280 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
73092892 281 (char *)&tv, sizeof(tv));
d7e09d03 282 if (rc != 0) {
2d00bd17 283 CERROR("Can't set socket send timeout %ld.%06d: %d\n",
d7e09d03
PT
284 (long)tv.tv_sec, (int)tv.tv_usec, rc);
285 return rc;
286 }
287 }
288
d7e09d03 289 then = jiffies;
480f40de 290 rc = kernel_sendmsg(sock, &msg, &iov, 1, nob);
d7e09d03 291 ticks -= jiffies - then;
d7e09d03
PT
292
293 if (rc == nob)
294 return 0;
295
296 if (rc < 0)
297 return rc;
298
299 if (rc == 0) {
73092892 300 CERROR("Unexpected zero rc\n");
fbe7c6c7 301 return -ECONNABORTED;
d7e09d03
PT
302 }
303
304 if (ticks <= 0)
305 return -EAGAIN;
306
307 buffer = ((char *)buffer) + rc;
308 nob -= rc;
309 }
fbe7c6c7 310 return 0;
d7e09d03 311}
1ad6a73e 312EXPORT_SYMBOL(lnet_sock_write);
d7e09d03
PT
313
314int
73092892 315lnet_sock_read(struct socket *sock, void *buffer, int nob, int timeout)
d7e09d03 316{
73092892
JS
317 int rc;
318 long ticks = timeout * HZ;
319 unsigned long then;
d7e09d03
PT
320 struct timeval tv;
321
73092892
JS
322 LASSERT(nob > 0);
323 LASSERT(ticks > 0);
d7e09d03
PT
324
325 for (;;) {
b2f42cfe 326 struct kvec iov = {
d7e09d03
PT
327 .iov_base = buffer,
328 .iov_len = nob
329 };
330 struct msghdr msg = {
73092892 331 .msg_flags = 0
d7e09d03
PT
332 };
333
334 /* Set receive timeout to remaining time */
335 tv = (struct timeval) {
336 .tv_sec = ticks / HZ,
337 .tv_usec = ((ticks % HZ) * 1000000) / HZ
338 };
80db2734 339 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
73092892 340 (char *)&tv, sizeof(tv));
d7e09d03
PT
341 if (rc != 0) {
342 CERROR("Can't set socket recv timeout %ld.%06d: %d\n",
343 (long)tv.tv_sec, (int)tv.tv_usec, rc);
344 return rc;
345 }
346
d7e09d03 347 then = jiffies;
b2f42cfe 348 rc = kernel_recvmsg(sock, &msg, &iov, 1, nob, 0);
d7e09d03 349 ticks -= jiffies - then;
d7e09d03
PT
350
351 if (rc < 0)
352 return rc;
353
354 if (rc == 0)
355 return -ECONNRESET;
356
357 buffer = ((char *)buffer) + rc;
358 nob -= rc;
359
360 if (nob == 0)
361 return 0;
362
363 if (ticks <= 0)
364 return -ETIMEDOUT;
365 }
366}
1ad6a73e 367EXPORT_SYMBOL(lnet_sock_read);
d7e09d03
PT
368
369static int
73092892
JS
370lnet_sock_create(struct socket **sockp, int *fatal, __u32 local_ip,
371 int local_port)
d7e09d03 372{
73092892
JS
373 struct sockaddr_in locaddr;
374 struct socket *sock;
375 int rc;
376 int option;
d7e09d03
PT
377
378 /* All errors are fatal except bind failure if the port is in use */
379 *fatal = 1;
380
73092892 381 rc = sock_create(PF_INET, SOCK_STREAM, 0, &sock);
d7e09d03
PT
382 *sockp = sock;
383 if (rc != 0) {
73092892 384 CERROR("Can't create socket: %d\n", rc);
fbe7c6c7 385 return rc;
d7e09d03
PT
386 }
387
d7e09d03 388 option = 1;
80db2734 389 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
73092892 390 (char *)&option, sizeof(option));
d7e09d03
PT
391 if (rc != 0) {
392 CERROR("Can't set SO_REUSEADDR for socket: %d\n", rc);
393 goto failed;
394 }
395
396 if (local_ip != 0 || local_port != 0) {
397 memset(&locaddr, 0, sizeof(locaddr));
398 locaddr.sin_family = AF_INET;
399 locaddr.sin_port = htons(local_port);
400 locaddr.sin_addr.s_addr = (local_ip == 0) ?
401 INADDR_ANY : htonl(local_ip);
402
5c2414ef
JS
403 rc = kernel_bind(sock, (struct sockaddr *)&locaddr,
404 sizeof(locaddr));
d7e09d03
PT
405 if (rc == -EADDRINUSE) {
406 CDEBUG(D_NET, "Port %d already in use\n", local_port);
407 *fatal = 0;
408 goto failed;
409 }
410 if (rc != 0) {
411 CERROR("Error trying to bind to port %d: %d\n",
412 local_port, rc);
413 goto failed;
414 }
415 }
d7e09d03
PT
416 return 0;
417
73092892 418failed:
d7e09d03
PT
419 sock_release(sock);
420 return rc;
421}
422
423int
73092892 424lnet_sock_setbuf(struct socket *sock, int txbufsize, int rxbufsize)
d7e09d03 425{
73092892
JS
426 int option;
427 int rc;
d7e09d03
PT
428
429 if (txbufsize != 0) {
430 option = txbufsize;
80db2734 431 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
73092892 432 (char *)&option, sizeof(option));
d7e09d03 433 if (rc != 0) {
73092892
JS
434 CERROR("Can't set send buffer %d: %d\n",
435 option, rc);
fbe7c6c7 436 return rc;
d7e09d03
PT
437 }
438 }
439
440 if (rxbufsize != 0) {
441 option = rxbufsize;
80db2734 442 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
c314c319 443 (char *)&option, sizeof(option));
d7e09d03 444 if (rc != 0) {
73092892
JS
445 CERROR("Can't set receive buffer %d: %d\n",
446 option, rc);
fbe7c6c7 447 return rc;
d7e09d03
PT
448 }
449 }
d7e09d03
PT
450 return 0;
451}
1ad6a73e 452EXPORT_SYMBOL(lnet_sock_setbuf);
d7e09d03
PT
453
454int
73092892 455lnet_sock_getaddr(struct socket *sock, bool remote, __u32 *ip, int *port)
d7e09d03
PT
456{
457 struct sockaddr_in sin;
73092892
JS
458 int len = sizeof(sin);
459 int rc;
d7e09d03 460
5c2414ef
JS
461 if (remote)
462 rc = kernel_getpeername(sock, (struct sockaddr *)&sin, &len);
463 else
464 rc = kernel_getsockname(sock, (struct sockaddr *)&sin, &len);
d7e09d03 465 if (rc != 0) {
73092892
JS
466 CERROR("Error %d getting sock %s IP/port\n",
467 rc, remote ? "peer" : "local");
d7e09d03
PT
468 return rc;
469 }
470
471 if (ip != NULL)
73092892 472 *ip = ntohl(sin.sin_addr.s_addr);
d7e09d03
PT
473
474 if (port != NULL)
73092892 475 *port = ntohs(sin.sin_port);
d7e09d03
PT
476
477 return 0;
478}
1ad6a73e 479EXPORT_SYMBOL(lnet_sock_getaddr);
d7e09d03
PT
480
481int
73092892 482lnet_sock_getbuf(struct socket *sock, int *txbufsize, int *rxbufsize)
d7e09d03 483{
73092892 484 if (txbufsize != NULL)
d7e09d03 485 *txbufsize = sock->sk->sk_sndbuf;
d7e09d03 486
73092892 487 if (rxbufsize != NULL)
d7e09d03 488 *rxbufsize = sock->sk->sk_rcvbuf;
d7e09d03
PT
489
490 return 0;
491}
1ad6a73e 492EXPORT_SYMBOL(lnet_sock_getbuf);
d7e09d03
PT
493
494int
73092892
JS
495lnet_sock_listen(struct socket **sockp, __u32 local_ip, int local_port,
496 int backlog)
d7e09d03 497{
73092892
JS
498 int fatal;
499 int rc;
d7e09d03 500
1ad6a73e 501 rc = lnet_sock_create(sockp, &fatal, local_ip, local_port);
d7e09d03
PT
502 if (rc != 0) {
503 if (!fatal)
504 CERROR("Can't create socket: port %d already in use\n",
505 local_port);
506 return rc;
507 }
508
5c2414ef 509 rc = kernel_listen(*sockp, backlog);
d7e09d03
PT
510 if (rc == 0)
511 return 0;
512
513 CERROR("Can't set listen backlog %d: %d\n", backlog, rc);
514 sock_release(*sockp);
515 return rc;
516}
1ad6a73e 517EXPORT_SYMBOL(lnet_sock_listen);
d7e09d03
PT
518
519int
73092892 520lnet_sock_accept(struct socket **newsockp, struct socket *sock)
d7e09d03 521{
73092892 522 wait_queue_t wait;
d7e09d03 523 struct socket *newsock;
73092892 524 int rc;
d7e09d03
PT
525
526 init_waitqueue_entry(&wait, current);
527
4420cfd3
JS
528 /*
529 * XXX this should add a ref to sock->ops->owner, if
530 * TCP could be a module
531 */
d7e09d03
PT
532 rc = sock_create_lite(PF_PACKET, sock->type, IPPROTO_TCP, &newsock);
533 if (rc) {
534 CERROR("Can't allocate socket\n");
535 return rc;
536 }
537
538 newsock->ops = sock->ops;
539
d7e09d03
PT
540 rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
541 if (rc == -EAGAIN) {
542 /* Nothing ready, so wait for activity */
834fe2e1
OD
543 set_current_state(TASK_INTERRUPTIBLE);
544 add_wait_queue(sk_sleep(sock->sk), &wait);
d7e09d03 545 schedule();
834fe2e1
OD
546 remove_wait_queue(sk_sleep(sock->sk), &wait);
547 set_current_state(TASK_RUNNING);
d7e09d03
PT
548 rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
549 }
550
d7e09d03
PT
551 if (rc != 0)
552 goto failed;
553
554 *newsockp = newsock;
555 return 0;
556
73092892 557failed:
d7e09d03
PT
558 sock_release(newsock);
559 return rc;
560}
1ad6a73e 561EXPORT_SYMBOL(lnet_sock_accept);
d7e09d03 562
d7e09d03 563int
73092892
JS
564lnet_sock_connect(struct socket **sockp, int *fatal, __u32 local_ip,
565 int local_port, __u32 peer_ip, int peer_port)
d7e09d03 566{
73092892
JS
567 struct sockaddr_in srvaddr;
568 int rc;
d7e09d03 569
1ad6a73e 570 rc = lnet_sock_create(sockp, fatal, local_ip, local_port);
d7e09d03
PT
571 if (rc != 0)
572 return rc;
573
73092892 574 memset(&srvaddr, 0, sizeof(srvaddr));
d7e09d03
PT
575 srvaddr.sin_family = AF_INET;
576 srvaddr.sin_port = htons(peer_port);
577 srvaddr.sin_addr.s_addr = htonl(peer_ip);
578
5c2414ef
JS
579 rc = kernel_connect(*sockp, (struct sockaddr *)&srvaddr,
580 sizeof(srvaddr), 0);
d7e09d03
PT
581 if (rc == 0)
582 return 0;
583
4420cfd3
JS
584 /*
585 * EADDRNOTAVAIL probably means we're already connected to the same
d7e09d03
PT
586 * peer/port on the same local port on a differently typed
587 * connection. Let our caller retry with a different local
4420cfd3
JS
588 * port...
589 */
d7e09d03
PT
590 *fatal = !(rc == -EADDRNOTAVAIL);
591
592 CDEBUG_LIMIT(*fatal ? D_NETERROR : D_NET,
73092892
JS
593 "Error %d connecting %pI4h/%d -> %pI4h/%d\n", rc,
594 &local_ip, local_port, &peer_ip, peer_port);
d7e09d03
PT
595
596 sock_release(*sockp);
597 return rc;
598}
1ad6a73e 599EXPORT_SYMBOL(lnet_sock_connect);
This page took 0.467052 seconds and 5 git commands to generate.