Whamcloud - gitweb
LU-10391 lnet: remove 'fatal' arg from lnet_{sock_}connect
[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 = cfs_time_seconds(timeout);
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                         jiffies_to_timeval(jiffies_left, &tv);
91                         rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO,
92                                                (char *)&tv, sizeof(tv));
93                         if (rc != 0) {
94                                 CERROR("Can't set socket send timeout "
95                                        "%ld.%06d: %d\n",
96                                        (long)tv.tv_sec, (int)tv.tv_usec, rc);
97                                 return rc;
98                         }
99                 }
100
101                 then = jiffies;
102                 rc = kernel_sendmsg(sock, &msg, &iov, 1, nob);
103                 jiffies_left -= jiffies - then;
104
105                 if (rc == nob)
106                         return 0;
107
108                 if (rc < 0)
109                         return rc;
110
111                 if (rc == 0) {
112                         CERROR("Unexpected zero rc\n");
113                         return -ECONNABORTED;
114                 }
115
116                 if (jiffies_left <= 0)
117                         return -EAGAIN;
118
119                 buffer = ((char *)buffer) + rc;
120                 nob -= rc;
121         }
122         return 0;
123 }
124 EXPORT_SYMBOL(lnet_sock_write);
125
126 int
127 lnet_sock_read(struct socket *sock, void *buffer, int nob, int timeout)
128 {
129         int             rc;
130         long            jiffies_left = cfs_time_seconds(timeout);
131         unsigned long   then;
132         struct timeval  tv;
133
134         LASSERT(nob > 0);
135         LASSERT(jiffies_left > 0);
136
137         for (;;) {
138                 struct kvec  iov = {
139                         .iov_base = buffer,
140                         .iov_len  = nob
141                 };
142                 struct msghdr msg = {
143                         .msg_flags      = 0
144                 };
145
146                 /* Set receive timeout to remaining time */
147                 jiffies_to_timeval(jiffies_left, &tv);
148                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO,
149                                        (char *)&tv, sizeof(tv));
150                 if (rc != 0) {
151                         CERROR("Can't set socket recv timeout %ld.%06d: %d\n",
152                                (long)tv.tv_sec, (int)tv.tv_usec, rc);
153                         return rc;
154                 }
155
156                 then = jiffies;
157                 rc = kernel_recvmsg(sock, &msg, &iov, 1, nob, 0);
158                 jiffies_left -= jiffies - then;
159
160                 if (rc < 0)
161                         return rc;
162
163                 if (rc == 0)
164                         return -ECONNRESET;
165
166                 buffer = ((char *)buffer) + rc;
167                 nob -= rc;
168
169                 if (nob == 0)
170                         return 0;
171
172                 if (jiffies_left <= 0)
173                         return -ETIMEDOUT;
174         }
175 }
176 EXPORT_SYMBOL(lnet_sock_read);
177
178 static int
179 lnet_sock_create(struct socket **sockp,
180                  __u32 local_ip, int local_port, struct net *ns)
181 {
182         struct sockaddr_in  locaddr;
183         struct socket      *sock;
184         int                 rc;
185         int                 option;
186
187 #ifdef HAVE_SOCK_CREATE_KERN_USE_NET
188         rc = sock_create_kern(ns, PF_INET, SOCK_STREAM, 0, &sock);
189 #else
190         rc = sock_create_kern(PF_INET, SOCK_STREAM, 0, &sock);
191 #endif
192         *sockp = sock;
193         if (rc != 0) {
194                 CERROR("Can't create socket: %d\n", rc);
195                 return rc;
196         }
197
198         option = 1;
199         rc = kernel_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
200                                (char *)&option, sizeof(option));
201         if (rc != 0) {
202                 CERROR("Can't set SO_REUSEADDR for socket: %d\n", rc);
203                 goto failed;
204         }
205
206         if (local_ip != 0 || local_port != 0) {
207                 memset(&locaddr, 0, sizeof(locaddr));
208                 locaddr.sin_family = AF_INET;
209                 locaddr.sin_port = htons(local_port);
210                 locaddr.sin_addr.s_addr = (local_ip == 0) ?
211                                           INADDR_ANY : htonl(local_ip);
212
213                 rc = kernel_bind(sock, (struct sockaddr *)&locaddr,
214                                  sizeof(locaddr));
215                 if (rc == -EADDRINUSE) {
216                         CDEBUG(D_NET, "Port %d already in use\n", local_port);
217                         goto failed;
218                 }
219                 if (rc != 0) {
220                         CERROR("Error trying to bind to port %d: %d\n",
221                                local_port, rc);
222                         goto failed;
223                 }
224         }
225         return 0;
226
227 failed:
228         sock_release(sock);
229         return rc;
230 }
231
232 int
233 lnet_sock_setbuf(struct socket *sock, int txbufsize, int rxbufsize)
234 {
235         int                 option;
236         int                 rc;
237
238         if (txbufsize != 0) {
239                 option = txbufsize;
240                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_SNDBUF,
241                                        (char *)&option, sizeof(option));
242                 if (rc != 0) {
243                         CERROR("Can't set send buffer %d: %d\n",
244                                 option, rc);
245                         return rc;
246                 }
247         }
248
249         if (rxbufsize != 0) {
250                 option = rxbufsize;
251                 rc = kernel_setsockopt(sock, SOL_SOCKET, SO_RCVBUF,
252                                        (char *)&option, sizeof(option));
253                 if (rc != 0) {
254                         CERROR("Can't set receive buffer %d: %d\n",
255                                 option, rc);
256                         return rc;
257                 }
258         }
259         return 0;
260 }
261 EXPORT_SYMBOL(lnet_sock_setbuf);
262
263 int
264 lnet_sock_getaddr(struct socket *sock, bool remote, __u32 *ip, int *port)
265 {
266         struct sockaddr_in sin;
267         int rc;
268 #ifndef HAVE_KERN_SOCK_GETNAME_2ARGS
269         int len = sizeof(sin);
270 #endif
271
272         if (remote)
273                 rc = lnet_kernel_getpeername(sock,
274                                              (struct sockaddr *)&sin, &len);
275         else
276                 rc = lnet_kernel_getsockname(sock,
277                                              (struct sockaddr *)&sin, &len);
278         if (rc < 0) {
279                 CERROR("Error %d getting sock %s IP/port\n",
280                         rc, remote ? "peer" : "local");
281                 return rc;
282         }
283
284         if (ip != NULL)
285                 *ip = ntohl(sin.sin_addr.s_addr);
286
287         if (port != NULL)
288                 *port = ntohs(sin.sin_port);
289
290         return 0;
291 }
292 EXPORT_SYMBOL(lnet_sock_getaddr);
293
294 int
295 lnet_sock_getbuf(struct socket *sock, int *txbufsize, int *rxbufsize)
296 {
297         if (txbufsize != NULL)
298                 *txbufsize = sock->sk->sk_sndbuf;
299
300         if (rxbufsize != NULL)
301                 *rxbufsize = sock->sk->sk_rcvbuf;
302
303         return 0;
304 }
305 EXPORT_SYMBOL(lnet_sock_getbuf);
306
307 int
308 lnet_sock_listen(struct socket **sockp,
309                    __u32 local_ip, int local_port, int backlog, struct net *ns)
310 {
311         int      rc;
312
313         rc = lnet_sock_create(sockp, local_ip, local_port, ns);
314         if (rc != 0) {
315                 if (rc == -EADDRINUSE)
316                         CERROR("Can't create socket: port %d already in use\n",
317                                local_port);
318                 return rc;
319         }
320
321         rc = kernel_listen(*sockp, backlog);
322         if (rc == 0)
323                 return 0;
324
325         CERROR("Can't set listen backlog %d: %d\n", backlog, rc);
326         sock_release(*sockp);
327         return rc;
328 }
329
330 int
331 lnet_sock_connect(struct socket **sockp,
332                   __u32 local_ip, int local_port,
333                   __u32 peer_ip, int peer_port,
334                   struct net *ns)
335 {
336         struct sockaddr_in  srvaddr;
337         int                 rc;
338
339         rc = lnet_sock_create(sockp, local_ip, local_port, ns);
340         if (rc != 0)
341                 return rc;
342
343         memset(&srvaddr, 0, sizeof(srvaddr));
344         srvaddr.sin_family = AF_INET;
345         srvaddr.sin_port = htons(peer_port);
346         srvaddr.sin_addr.s_addr = htonl(peer_ip);
347
348         rc = kernel_connect(*sockp, (struct sockaddr *)&srvaddr,
349                             sizeof(srvaddr), 0);
350         if (rc == 0)
351                 return 0;
352
353         /* EADDRNOTAVAIL probably means we're already connected to the same
354          * peer/port on the same local port on a differently typed
355          * connection.  Let our caller retry with a different local
356          * port... */
357
358         CDEBUG_LIMIT(rc == -EADDRNOTAVAIL ? D_NET : D_NETERROR,
359                      "Error %d connecting %pI4h/%d -> %pI4h/%d\n", rc,
360                      &local_ip, local_port, &peer_ip, peer_port);
361
362         sock_release(*sockp);
363         return rc;
364 }