Whamcloud - gitweb
LU-12400 lnet: SO_SNDTIMEO, SO_RCVTIMEO removed
[fs/lustre-release.git] / lnet / lnet / lib-socket.c
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
18  * http://www.gnu.org/licenses/gpl-2.0.html
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  *
26  * Copyright (c) 2015, 2017, Intel Corporation.
27  */
28 /*
29  * This file is part of Lustre, http://www.lustre.org/
30  * Lustre is a trademark of Sun Microsystems, Inc.
31  */
32 #define DEBUG_SUBSYSTEM S_LNET
33
34 #include <linux/if.h>
35 #include <linux/in.h>
36 #include <linux/net.h>
37 #include <linux/file.h>
38 #include <linux/pagemap.h>
39 /* For sys_open & sys_close */
40 #include <linux/syscalls.h>
41 #include <net/sock.h>
42
43 #include <libcfs/libcfs.h>
44 #include <lnet/lib-lnet.h>
45
46 /*
47  * kernel 5.1: commit 7f1bc6e95d7840d4305595b3e4025cddda88cee5
48  * Y2038 64-bit time.
49  *  SO_TIMESTAMP, SO_TIMESTAMPNS and SO_TIMESTAMPING options, the
50  *  way they are currently defined, are not y2038 safe.
51  *  Subsequent patches in the series add new y2038 safe versions
52  *  of these options which provide 64 bit timestamps on all
53  *  architectures uniformly.
54  *  Hence, rename existing options with OLD tag suffixes.
55  *
56  * NOTE: When updating to timespec64 change change these to '_NEW'.
57  *
58  */
59 #ifndef SO_SNDTIMEO
60 #define SO_SNDTIMEO SO_SNDTIMEO_OLD
61 #endif
62
63 #ifndef SO_RCVTIMEO
64 #define SO_RCVTIMEO SO_RCVTIMEO_OLD
65 #endif
66
67 int
68 lnet_sock_write(struct socket *sock, void *buffer, int nob, int timeout)
69 {
70         int             rc;
71         long            jiffies_left = timeout * msecs_to_jiffies(MSEC_PER_SEC);
72         unsigned long   then;
73         struct timeval  tv;
74
75         LASSERT(nob > 0);
76         /* Caller may pass a zero timeout if she thinks the socket buffer is
77          * empty enough to take the whole message immediately */
78
79         for (;;) {
80                 struct kvec  iov = {
81                         .iov_base = buffer,
82                         .iov_len  = nob
83                 };
84                 struct msghdr msg = {
85                         .msg_flags      = (timeout == 0) ? MSG_DONTWAIT : 0
86                 };
87
88                 if (timeout != 0) {
89                         /* Set send timeout to remaining time */
90                         tv = (struct timeval) {
91                                 .tv_sec = jiffies_left /
92                                           msecs_to_jiffies(MSEC_PER_SEC),
93                                 .tv_usec = ((jiffies_left %
94                                              msecs_to_jiffies(MSEC_PER_SEC)) *
95                                              USEC_PER_SEC) /
96                                              msecs_to_jiffies(MSEC_PER_SEC)
97                         };
98
99                         rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
100                                                (char *)&tv, sizeof(tv));
101                         if (rc != 0) {
102                                 CERROR("Can't set socket send timeout "
103                                        "%ld.%06d: %d\n",
104                                        (long)tv.tv_sec, (int)tv.tv_usec, rc);
105                                 return rc;
106                         }
107                 }
108
109                 then = jiffies;
110                 rc = kernel_sendmsg(sock, &msg, &iov, 1, nob);
111                 jiffies_left -= jiffies - then;
112
113                 if (rc == nob)
114                         return 0;
115
116                 if (rc < 0)
117                         return rc;
118
119                 if (rc == 0) {
120                         CERROR("Unexpected zero rc\n");
121                         return -ECONNABORTED;
122                 }
123
124                 if (jiffies_left <= 0)
125                         return -EAGAIN;
126
127                 buffer = ((char *)buffer) + rc;
128                 nob -= rc;
129         }
130         return 0;
131 }
132 EXPORT_SYMBOL(lnet_sock_write);
133
134 int
135 lnet_sock_read(struct socket *sock, void *buffer, int nob, int timeout)
136 {
137         int             rc;
138         long            jiffies_left = timeout * msecs_to_jiffies(MSEC_PER_SEC);
139         unsigned long   then;
140         struct timeval  tv;
141
142         LASSERT(nob > 0);
143         LASSERT(jiffies_left > 0);
144
145         for (;;) {
146                 struct kvec  iov = {
147                         .iov_base = buffer,
148                         .iov_len  = nob
149                 };
150                 struct msghdr msg = {
151                         .msg_flags      = 0
152                 };
153
154                 /* Set receive timeout to remaining time */
155                 tv = (struct timeval) {
156                         .tv_sec = jiffies_left / msecs_to_jiffies(MSEC_PER_SEC),
157                         .tv_usec = ((jiffies_left %
158                                         msecs_to_jiffies(MSEC_PER_SEC)) *
159                                         USEC_PER_SEC) /
160                                         msecs_to_jiffies(MSEC_PER_SEC)
161                 };
162                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
163                                        (char *)&tv, sizeof(tv));
164                 if (rc != 0) {
165                         CERROR("Can't set socket recv timeout %ld.%06d: %d\n",
166                                (long)tv.tv_sec, (int)tv.tv_usec, rc);
167                         return rc;
168                 }
169
170                 then = jiffies;
171                 rc = kernel_recvmsg(sock, &msg, &iov, 1, nob, 0);
172                 jiffies_left -= jiffies - then;
173
174                 if (rc < 0)
175                         return rc;
176
177                 if (rc == 0)
178                         return -ECONNRESET;
179
180                 buffer = ((char *)buffer) + rc;
181                 nob -= rc;
182
183                 if (nob == 0)
184                         return 0;
185
186                 if (jiffies_left <= 0)
187                         return -ETIMEDOUT;
188         }
189 }
190 EXPORT_SYMBOL(lnet_sock_read);
191
192 static int
193 lnet_sock_create(struct socket **sockp, int *fatal,
194                  __u32 local_ip, int local_port)
195 {
196         struct sockaddr_in  locaddr;
197         struct socket      *sock;
198         int                 rc;
199         int                 option;
200
201         /* All errors are fatal except bind failure if the port is in use */
202         *fatal = 1;
203
204 #ifdef HAVE_SOCK_CREATE_KERN_USE_NET
205         rc = sock_create_kern(&init_net, PF_INET, SOCK_STREAM, 0, &sock);
206 #else
207         rc = sock_create_kern(PF_INET, SOCK_STREAM, 0, &sock);
208 #endif
209         *sockp = sock;
210         if (rc != 0) {
211                 CERROR("Can't create socket: %d\n", rc);
212                 return rc;
213         }
214
215         option = 1;
216         rc = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
217                                (char *)&option, sizeof(option));
218         if (rc != 0) {
219                 CERROR("Can't set SO_REUSEADDR for socket: %d\n", rc);
220                 goto failed;
221         }
222
223         if (local_ip != 0 || local_port != 0) {
224                 memset(&locaddr, 0, sizeof(locaddr));
225                 locaddr.sin_family = AF_INET;
226                 locaddr.sin_port = htons(local_port);
227                 locaddr.sin_addr.s_addr = (local_ip == 0) ?
228                                           INADDR_ANY : htonl(local_ip);
229
230                 rc = kernel_bind(sock, (struct sockaddr *)&locaddr,
231                                  sizeof(locaddr));
232                 if (rc == -EADDRINUSE) {
233                         CDEBUG(D_NET, "Port %d already in use\n", local_port);
234                         *fatal = 0;
235                         goto failed;
236                 }
237                 if (rc != 0) {
238                         CERROR("Error trying to bind to port %d: %d\n",
239                                local_port, rc);
240                         goto failed;
241                 }
242         }
243         return 0;
244
245 failed:
246         sock_release(sock);
247         return rc;
248 }
249
250 int
251 lnet_sock_setbuf(struct socket *sock, int txbufsize, int rxbufsize)
252 {
253         int                 option;
254         int                 rc;
255
256         if (txbufsize != 0) {
257                 option = txbufsize;
258                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
259                                        (char *)&option, sizeof(option));
260                 if (rc != 0) {
261                         CERROR("Can't set send buffer %d: %d\n",
262                                 option, rc);
263                         return rc;
264                 }
265         }
266
267         if (rxbufsize != 0) {
268                 option = rxbufsize;
269                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
270                                        (char *)&option, sizeof(option));
271                 if (rc != 0) {
272                         CERROR("Can't set receive buffer %d: %d\n",
273                                 option, rc);
274                         return rc;
275                 }
276         }
277         return 0;
278 }
279 EXPORT_SYMBOL(lnet_sock_setbuf);
280
281 int
282 lnet_sock_getaddr(struct socket *sock, bool remote, __u32 *ip, int *port)
283 {
284         struct sockaddr_in sin;
285         int rc;
286 #ifndef HAVE_KERN_SOCK_GETNAME_2ARGS
287         int len = sizeof(sin);
288 #endif
289
290         if (remote)
291                 rc = lnet_kernel_getpeername(sock,
292                                              (struct sockaddr *)&sin, &len);
293         else
294                 rc = lnet_kernel_getsockname(sock,
295                                              (struct sockaddr *)&sin, &len);
296         if (rc < 0) {
297                 CERROR("Error %d getting sock %s IP/port\n",
298                         rc, remote ? "peer" : "local");
299                 return rc;
300         }
301
302         if (ip != NULL)
303                 *ip = ntohl(sin.sin_addr.s_addr);
304
305         if (port != NULL)
306                 *port = ntohs(sin.sin_port);
307
308         return 0;
309 }
310 EXPORT_SYMBOL(lnet_sock_getaddr);
311
312 int
313 lnet_sock_getbuf(struct socket *sock, int *txbufsize, int *rxbufsize)
314 {
315         if (txbufsize != NULL)
316                 *txbufsize = sock->sk->sk_sndbuf;
317
318         if (rxbufsize != NULL)
319                 *rxbufsize = sock->sk->sk_rcvbuf;
320
321         return 0;
322 }
323 EXPORT_SYMBOL(lnet_sock_getbuf);
324
325 int
326 lnet_sock_listen(struct socket **sockp,
327                    __u32 local_ip, int local_port, int backlog)
328 {
329         int      fatal;
330         int      rc;
331
332         rc = lnet_sock_create(sockp, &fatal, local_ip, local_port);
333         if (rc != 0) {
334                 if (!fatal)
335                         CERROR("Can't create socket: port %d already in use\n",
336                                local_port);
337                 return rc;
338         }
339
340         rc = kernel_listen(*sockp, backlog);
341         if (rc == 0)
342                 return 0;
343
344         CERROR("Can't set listen backlog %d: %d\n", backlog, rc);
345         sock_release(*sockp);
346         return rc;
347 }
348
349 #ifndef HAVE_SK_SLEEP
350 static inline wait_queue_head_t *sk_sleep(struct sock *sk)
351 {
352         return sk->sk_sleep;
353 }
354 #endif
355
356 int
357 lnet_sock_accept(struct socket **newsockp, struct socket *sock)
358 {
359         wait_queue_entry_t wait;
360         struct socket *newsock;
361         int            rc;
362
363         /* XXX this should add a ref to sock->ops->owner, if
364          * TCP could be a module */
365         rc = sock_create_lite(PF_PACKET, sock->type, IPPROTO_TCP, &newsock);
366         if (rc) {
367                 CERROR("Can't allocate socket\n");
368                 return rc;
369         }
370
371         newsock->ops = sock->ops;
372
373 #ifdef HAVE_KERN_SOCK_ACCEPT_FLAG_ARG
374         rc = sock->ops->accept(sock, newsock, O_NONBLOCK, false);
375 #else
376         rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
377 #endif
378         if (rc == -EAGAIN) {
379                 /* Nothing ready, so wait for activity */
380                 init_waitqueue_entry(&wait, current);
381                 add_wait_queue(sk_sleep(sock->sk), &wait);
382                 set_current_state(TASK_INTERRUPTIBLE);
383                 schedule();
384                 remove_wait_queue(sk_sleep(sock->sk), &wait);
385 #ifdef HAVE_KERN_SOCK_ACCEPT_FLAG_ARG
386                 rc = sock->ops->accept(sock, newsock, O_NONBLOCK, false);
387 #else
388                 rc = sock->ops->accept(sock, newsock, O_NONBLOCK);
389 #endif
390         }
391
392         if (rc != 0)
393                 goto failed;
394
395         *newsockp = newsock;
396         return 0;
397
398 failed:
399         sock_release(newsock);
400         return rc;
401 }
402
403 int
404 lnet_sock_connect(struct socket **sockp, int *fatal,
405                   __u32 local_ip, int local_port,
406                   __u32 peer_ip, int peer_port)
407 {
408         struct sockaddr_in  srvaddr;
409         int                 rc;
410
411         rc = lnet_sock_create(sockp, fatal, local_ip, local_port);
412         if (rc != 0)
413                 return rc;
414
415         memset(&srvaddr, 0, sizeof(srvaddr));
416         srvaddr.sin_family = AF_INET;
417         srvaddr.sin_port = htons(peer_port);
418         srvaddr.sin_addr.s_addr = htonl(peer_ip);
419
420         rc = kernel_connect(*sockp, (struct sockaddr *)&srvaddr,
421                             sizeof(srvaddr), 0);
422         if (rc == 0)
423                 return 0;
424
425         /* EADDRNOTAVAIL probably means we're already connected to the same
426          * peer/port on the same local port on a differently typed
427          * connection.  Let our caller retry with a different local
428          * port... */
429         *fatal = !(rc == -EADDRNOTAVAIL);
430
431         CDEBUG_LIMIT(*fatal ? D_NETERROR : D_NET,
432                "Error %d connecting %pI4h/%d -> %pI4h/%d\n", rc,
433                &local_ip, local_port, &peer_ip, peer_port);
434
435         sock_release(*sockp);
436         return rc;
437 }