Whamcloud - gitweb
LU-1346 libcfs: replace libcfs wrappers with kernel API
[fs/lustre-release.git] / lnet / klnds / socklnd / socklnd_lib-linux.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.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2011, Whamcloud, Inc.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  */
36
37 #include "socklnd.h"
38
39 # if defined(CONFIG_SYSCTL) && !CFS_SYSFS_MODULE_PARM
40
41 #ifndef HAVE_SYSCTL_UNNUMBERED
42
43 enum {
44         SOCKLND_TIMEOUT = 1,
45         SOCKLND_CREDITS,
46         SOCKLND_PEER_TXCREDITS,
47         SOCKLND_PEER_RTRCREDITS,
48         SOCKLND_PEER_TIMEOUT,
49         SOCKLND_NCONNDS,
50         SOCKLND_RECONNECTS_MIN,
51         SOCKLND_RECONNECTS_MAX,
52         SOCKLND_EAGER_ACK,
53         SOCKLND_ZERO_COPY,
54         SOCKLND_TYPED,
55         SOCKLND_BULK_MIN,
56         SOCKLND_RX_BUFFER_SIZE,
57         SOCKLND_TX_BUFFER_SIZE,
58         SOCKLND_NAGLE,
59         SOCKLND_IRQ_AFFINITY,
60         SOCKLND_ROUND_ROBIN,
61         SOCKLND_KEEPALIVE,
62         SOCKLND_KEEPALIVE_IDLE,
63         SOCKLND_KEEPALIVE_COUNT,
64         SOCKLND_KEEPALIVE_INTVL,
65         SOCKLND_BACKOFF_INIT,
66         SOCKLND_BACKOFF_MAX,
67         SOCKLND_PROTOCOL,
68         SOCKLND_ZERO_COPY_RECV,
69         SOCKLND_ZERO_COPY_RECV_MIN_NFRAGS
70 };
71 #else
72
73 #define SOCKLND_TIMEOUT         CTL_UNNUMBERED
74 #define SOCKLND_CREDITS         CTL_UNNUMBERED
75 #define SOCKLND_PEER_TXCREDITS  CTL_UNNUMBERED
76 #define SOCKLND_PEER_RTRCREDITS  CTL_UNNUMBERED
77 #define SOCKLND_PEER_TIMEOUT    CTL_UNNUMBERED
78 #define SOCKLND_NCONNDS         CTL_UNNUMBERED
79 #define SOCKLND_RECONNECTS_MIN  CTL_UNNUMBERED
80 #define SOCKLND_RECONNECTS_MAX  CTL_UNNUMBERED
81 #define SOCKLND_EAGER_ACK       CTL_UNNUMBERED
82 #define SOCKLND_ZERO_COPY       CTL_UNNUMBERED
83 #define SOCKLND_TYPED           CTL_UNNUMBERED
84 #define SOCKLND_BULK_MIN        CTL_UNNUMBERED
85 #define SOCKLND_RX_BUFFER_SIZE  CTL_UNNUMBERED
86 #define SOCKLND_TX_BUFFER_SIZE  CTL_UNNUMBERED
87 #define SOCKLND_NAGLE           CTL_UNNUMBERED
88 #define SOCKLND_IRQ_AFFINITY    CTL_UNNUMBERED
89 #define SOCKLND_ROUND_ROBIN     CTL_UNNUMBERED
90 #define SOCKLND_KEEPALIVE       CTL_UNNUMBERED
91 #define SOCKLND_KEEPALIVE_IDLE  CTL_UNNUMBERED
92 #define SOCKLND_KEEPALIVE_COUNT CTL_UNNUMBERED
93 #define SOCKLND_KEEPALIVE_INTVL CTL_UNNUMBERED
94 #define SOCKLND_BACKOFF_INIT    CTL_UNNUMBERED
95 #define SOCKLND_BACKOFF_MAX     CTL_UNNUMBERED
96 #define SOCKLND_PROTOCOL        CTL_UNNUMBERED
97 #define SOCKLND_ZERO_COPY_RECV  CTL_UNNUMBERED
98 #define SOCKLND_ZERO_COPY_RECV_MIN_NFRAGS CTL_UNNUMBERED
99 #endif
100
101 static cfs_sysctl_table_t ksocknal_ctl_table[] = {
102         {
103                 .ctl_name = SOCKLND_TIMEOUT,
104                 .procname = "timeout",
105                 .data     = &ksocknal_tunables.ksnd_timeout,
106                 .maxlen   = sizeof (int),
107                 .mode     = 0644,
108                 .proc_handler = &proc_dointvec,
109                 .strategy = &sysctl_intvec,
110         },
111         {
112                 .ctl_name = SOCKLND_CREDITS,
113                 .procname = "credits",
114                 .data     = &ksocknal_tunables.ksnd_credits,
115                 .maxlen   = sizeof (int),
116                 .mode     = 0444,
117                 .proc_handler = &proc_dointvec,
118                 .strategy = &sysctl_intvec,
119         },
120          {
121                 .ctl_name = SOCKLND_PEER_TXCREDITS,
122                 .procname = "peer_credits",
123                 .data     = &ksocknal_tunables.ksnd_peertxcredits,
124                 .maxlen   = sizeof (int),
125                 .mode     = 0444,
126                 .proc_handler = &proc_dointvec,
127                 .strategy = &sysctl_intvec,
128         },
129          {
130                 .ctl_name = SOCKLND_PEER_RTRCREDITS,
131                 .procname = "peer_buffer_credits",
132                 .data     = &ksocknal_tunables.ksnd_peerrtrcredits,
133                 .maxlen   = sizeof (int),
134                 .mode     = 0444,
135                 .proc_handler = &proc_dointvec,
136                 .strategy = &sysctl_intvec,
137         },
138         {
139                 .ctl_name = SOCKLND_PEER_TIMEOUT,
140                 .procname = "peer_timeout",
141                 .data     = &ksocknal_tunables.ksnd_peertimeout,
142                 .maxlen   = sizeof (int),
143                 .mode     = 0444,
144                 .proc_handler = &proc_dointvec
145                 .strategy = &sysctl_intvec,
146         },
147         {
148                 .ctl_name = SOCKLND_NCONNDS,
149                 .procname = "nconnds",
150                 .data     = &ksocknal_tunables.ksnd_nconnds,
151                 .maxlen   = sizeof (int),
152                 .mode     = 0444,
153                 .proc_handler = &proc_dointvec,
154                 .strategy = &sysctl_intvec,
155         },
156         {
157                 .ctl_name = SOCKLND_RECONNECTS_MIN,
158                 .procname = "min_reconnectms",
159                 .data     = &ksocknal_tunables.ksnd_min_reconnectms,
160                 .maxlen   = sizeof (int),
161                 .mode     = 0444,
162                 .proc_handler = &proc_dointvec,
163                 .strategy = &sysctl_intvec,
164         },
165         {
166                 .ctl_name = SOCKLND_RECONNECTS_MAX,
167                 .procname = "max_reconnectms",
168                 .data     = &ksocknal_tunables.ksnd_max_reconnectms,
169                 .maxlen   = sizeof (int),
170                 .mode     = 0444,
171                 .proc_handler = &proc_dointvec,
172                 .strategy = &sysctl_intvec,
173         },
174         {
175                 .ctl_name = SOCKLND_EAGER_ACK,
176                 .procname = "eager_ack",
177                 .data     = &ksocknal_tunables.ksnd_eager_ack,
178                 .maxlen   = sizeof (int),
179                 .mode     = 0644,
180                 .proc_handler = &proc_dointvec,
181                 .strategy = &sysctl_intvec,
182         },
183         {
184                 .ctl_name = SOCKLND_ZERO_COPY,
185                 .procname = "zero_copy",
186                 .data     = &ksocknal_tunables.ksnd_zc_min_payload,
187                 .maxlen   = sizeof (int),
188                 .mode     = 0644,
189                 .proc_handler = &proc_dointvec,
190                 .strategy = &sysctl_intvec,
191         },
192         {
193                 .ctl_name = SOCKLND_ZERO_COPY_RECV,
194                 .procname = "zero_copy_recv",
195                 .data     = &ksocknal_tunables.ksnd_zc_recv,
196                 .maxlen   = sizeof (int),
197                 .mode     = 0644,
198                 .proc_handler = &proc_dointvec,
199                 .strategy = &sysctl_intvec,
200         },
201
202         {
203                 .ctl_name = SOCKLND_ZERO_COPY_RECV_MIN_NFRAGS,
204                 .procname = "zero_copy_recv",
205                 .data     = &ksocknal_tunables.ksnd_zc_recv_min_nfrags,
206                 .maxlen   = sizeof (int),
207                 .mode     = 0644,
208                 .proc_handler = &proc_dointvec,
209                 .strategy = &sysctl_intvec,
210         },
211         {
212                 .ctl_name = SOCKLND_TYPED,
213                 .procname = "typed",
214                 .data     = &ksocknal_tunables.ksnd_typed_conns,
215                 .maxlen   = sizeof (int),
216                 .mode     = 0444,
217                 .proc_handler = &proc_dointvec,
218                 .strategy = &sysctl_intvec,
219         },
220         {
221                 .ctl_name = SOCKLND_BULK_MIN,
222                 .procname = "min_bulk",
223                 .data     = &ksocknal_tunables.ksnd_min_bulk,
224                 .maxlen   = sizeof (int),
225                 .mode     = 0644,
226                 .proc_handler = &proc_dointvec,
227                 .strategy = &sysctl_intvec,
228         },
229         {
230                 .ctl_name = SOCKLND_RX_BUFFER_SIZE,
231                 .procname = "rx_buffer_size",
232                 .data     = &ksocknal_tunables.ksnd_rx_buffer_size,
233                 .maxlen   = sizeof(int),
234                 .mode     = 0644,
235                 .proc_handler = &proc_dointvec,
236                 .strategy = &sysctl_intvec,
237         },
238         {
239                 .ctl_name = SOCKLND_TX_BUFFER_SIZE,
240                 .procname = "tx_buffer_size",
241                 .data     = &ksocknal_tunables.ksnd_tx_buffer_size,
242                 .maxlen   = sizeof(int),
243                 .mode     = 0644,
244                 .proc_handler = &proc_dointvec,
245                 .strategy = &sysctl_intvec,
246         },
247         {
248                 .ctl_name = SOCKLND_NAGLE,
249                 .procname = "nagle",
250                 .data     = &ksocknal_tunables.ksnd_nagle,
251                 .maxlen   = sizeof(int),
252                 .mode     = 0644,
253                 .proc_handler = &proc_dointvec,
254                 .strategy = &sysctl_intvec,
255         },
256 #ifdef CPU_AFFINITY
257         {
258                 .ctl_name = SOCKLND_IRQ_AFFINITY,
259                 .procname = "irq_affinity",
260                 .data     = &ksocknal_tunables.ksnd_irq_affinity,
261                 .maxlen   = sizeof(int),
262                 .mode     = 0644,
263                 .proc_handler = &proc_dointvec,
264                 .strategy = &sysctl_intvec,
265         },
266 #endif
267         {
268                 .ctl_name = SOCKLND_ROUND_ROBIN,
269                 .procname = "round_robin",
270                 .data     = &ksocknal_tunables.ksnd_round_robin,
271                 .maxlen   = sizeof(int),
272                 .mode     = 0644,
273                 .proc_handler = &proc_dointvec,
274                 .strategy = &sysctl_intvec,
275         },
276         {
277                 .ctl_name = SOCKLND_KEEPALIVE,
278                 .procname = "keepalive",
279                 .data     = &ksocknal_tunables.ksnd_keepalive,
280                 .maxlen   = sizeof(int),
281                 .mode     = 0644,
282                 .proc_handler = &proc_dointvec,
283                 .strategy = &sysctl_intvec,
284         },
285         {
286                 .ctl_name = SOCKLND_KEEPALIVE_IDLE,
287                 .procname = "keepalive_idle",
288                 .data     = &ksocknal_tunables.ksnd_keepalive_idle,
289                 .maxlen   = sizeof(int),
290                 .mode     = 0644,
291                 .proc_handler = &proc_dointvec,
292                 .strategy = &sysctl_intvec,
293         },
294         {
295                 .ctl_name = SOCKLND_KEEPALIVE_COUNT,
296                 .procname = "keepalive_count",
297                 .data     = &ksocknal_tunables.ksnd_keepalive_count,
298                 .maxlen   = sizeof(int),
299                 .mode     = 0644,
300                 .proc_handler = &proc_dointvec,
301                 .strategy = &sysctl_intvec,
302         },
303         {
304                 .ctl_name = SOCKLND_KEEPALIVE_INTVL,
305                 .procname = "keepalive_intvl",
306                 .data     = &ksocknal_tunables.ksnd_keepalive_intvl,
307                 .maxlen   = sizeof(int),
308                 .mode     = 0644,
309                 .proc_handler = &proc_dointvec,
310                 .strategy = &sysctl_intvec,
311         },
312 #ifdef SOCKNAL_BACKOFF
313         {
314                 .ctl_name = SOCKLND_BACKOFF_INIT,
315                 .procname = "backoff_init",
316                 .data     = &ksocknal_tunables.ksnd_backoff_init,
317                 .maxlen   = sizeof(int),
318                 .mode     = 0644,
319                 .proc_handler = &proc_dointvec,
320                 .strategy = &sysctl_intvec,
321         },
322         {
323                 .ctl_name = SOCKLND_BACKOFF_MAX,
324                 .procname = "backoff_max",
325                 .data     = &ksocknal_tunables.ksnd_backoff_max,
326                 .maxlen   = sizeof(int),
327                 .mode     = 0644,
328                 .proc_handler = &proc_dointvec,
329                 .strategy = &sysctl_intvec,
330         },
331 #endif
332 #if SOCKNAL_VERSION_DEBUG
333         {
334                 .ctl_name = SOCKLND_PROTOCOL,
335                 .procname = "protocol",
336                 .data     = &ksocknal_tunables.ksnd_protocol,
337                 .maxlen   = sizeof(int),
338                 .mode     = 0644,
339                 .proc_handler = &proc_dointvec,
340                 .strategy = &sysctl_intvec,
341         },
342 #endif
343         {0}
344 };
345
346
347 cfs_sysctl_table_t ksocknal_top_ctl_table[] = {
348         {
349                 .ctl_name = CTL_SOCKLND,
350                 .procname = "socknal",
351                 .data     = NULL,
352                 .maxlen   = 0,
353                 .mode     = 0555,
354                 .child    = ksocknal_ctl_table
355         },
356         { 0 }
357 };
358
359 int
360 ksocknal_lib_tunables_init ()
361 {
362         if (!*ksocknal_tunables.ksnd_typed_conns) {
363                 int rc = -EINVAL;
364 #if SOCKNAL_VERSION_DEBUG
365                 if (*ksocknal_tunables.ksnd_protocol < 3)
366                         rc = 0;
367 #endif
368                 if (rc != 0) {
369                         CERROR("Protocol V3.x MUST have typed connections\n");
370                         return rc;
371                 }
372         }
373
374         if (*ksocknal_tunables.ksnd_zc_recv_min_nfrags < 2)
375                 *ksocknal_tunables.ksnd_zc_recv_min_nfrags = 2;
376         if (*ksocknal_tunables.ksnd_zc_recv_min_nfrags > LNET_MAX_IOV)
377                 *ksocknal_tunables.ksnd_zc_recv_min_nfrags = LNET_MAX_IOV;
378
379         ksocknal_tunables.ksnd_sysctl =
380                 cfs_register_sysctl_table(ksocknal_top_ctl_table, 0);
381
382         if (ksocknal_tunables.ksnd_sysctl == NULL)
383                 CWARN("Can't setup /proc tunables\n");
384
385         return 0;
386 }
387
388 void
389 ksocknal_lib_tunables_fini ()
390 {
391         if (ksocknal_tunables.ksnd_sysctl != NULL)
392                 cfs_unregister_sysctl_table(ksocknal_tunables.ksnd_sysctl);
393 }
394 #else
395 int
396 ksocknal_lib_tunables_init ()
397 {
398         return 0;
399 }
400
401 void
402 ksocknal_lib_tunables_fini ()
403 {
404 }
405 #endif /* # if CONFIG_SYSCTL && !CFS_SYSFS_MODULE_PARM */
406
407 int
408 ksocknal_lib_get_conn_addrs (ksock_conn_t *conn)
409 {
410         int rc = libcfs_sock_getaddr(conn->ksnc_sock, 1,
411                                      &conn->ksnc_ipaddr,
412                                      &conn->ksnc_port);
413
414         /* Didn't need the {get,put}connsock dance to deref ksnc_sock... */
415         LASSERT (!conn->ksnc_closing);
416
417         if (rc != 0) {
418                 CERROR ("Error %d getting sock peer IP\n", rc);
419                 return rc;
420         }
421
422         rc = libcfs_sock_getaddr(conn->ksnc_sock, 0,
423                                  &conn->ksnc_myipaddr, NULL);
424         if (rc != 0) {
425                 CERROR ("Error %d getting sock local IP\n", rc);
426                 return rc;
427         }
428
429         return 0;
430 }
431
432 int
433 ksocknal_lib_zc_capable(ksock_conn_t *conn)
434 {
435         int  caps = conn->ksnc_sock->sk->sk_route_caps;
436
437         if (conn->ksnc_proto == &ksocknal_protocol_v1x)
438                 return 0;
439
440         /* ZC if the socket supports scatter/gather and doesn't need software
441          * checksums */
442         return ((caps & NETIF_F_SG) != 0 && (caps & NETIF_F_ALL_CSUM) != 0);
443 }
444
445 int
446 ksocknal_lib_send_iov (ksock_conn_t *conn, ksock_tx_t *tx)
447 {
448         struct socket *sock = conn->ksnc_sock;
449         int            nob;
450         int            rc;
451
452         if (*ksocknal_tunables.ksnd_enable_csum        && /* checksum enabled */
453             conn->ksnc_proto == &ksocknal_protocol_v2x && /* V2.x connection  */
454             tx->tx_nob == tx->tx_resid                 && /* frist sending    */
455             tx->tx_msg.ksm_csum == 0)                     /* not checksummed  */
456                 ksocknal_lib_csum_tx(tx);
457
458         /* NB we can't trust socket ops to either consume our iovs
459          * or leave them alone. */
460
461         {
462 #if SOCKNAL_SINGLE_FRAG_TX
463                 struct iovec    scratch;
464                 struct iovec   *scratchiov = &scratch;
465                 unsigned int    niov = 1;
466 #else
467                 struct iovec   *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
468                 unsigned int    niov = tx->tx_niov;
469 #endif
470                 struct msghdr msg = {
471                         .msg_name       = NULL,
472                         .msg_namelen    = 0,
473                         .msg_iov        = scratchiov,
474                         .msg_iovlen     = niov,
475                         .msg_control    = NULL,
476                         .msg_controllen = 0,
477                         .msg_flags      = MSG_DONTWAIT
478                 };
479                 mm_segment_t oldmm = get_fs();
480                 int  i;
481
482                 for (nob = i = 0; i < niov; i++) {
483                         scratchiov[i] = tx->tx_iov[i];
484                         nob += scratchiov[i].iov_len;
485                 }
486
487                 if (!cfs_list_empty(&conn->ksnc_tx_queue) ||
488                     nob < tx->tx_resid)
489                         msg.msg_flags |= MSG_MORE;
490
491                 set_fs (KERNEL_DS);
492                 rc = sock_sendmsg(sock, &msg, nob);
493                 set_fs (oldmm);
494         }
495         return rc;
496 }
497
498 int
499 ksocknal_lib_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx)
500 {
501         struct socket *sock = conn->ksnc_sock;
502         lnet_kiov_t   *kiov = tx->tx_kiov;
503         int            rc;
504         int            nob;
505
506         /* Not NOOP message */
507         LASSERT (tx->tx_lnetmsg != NULL);
508
509         /* NB we can't trust socket ops to either consume our iovs
510          * or leave them alone. */
511         if (tx->tx_msg.ksm_zc_cookies[0] != 0) {
512                 /* Zero copy is enabled */
513                 struct sock   *sk = sock->sk;
514                 struct page   *page = kiov->kiov_page;
515                 int            offset = kiov->kiov_offset;
516                 int            fragsize = kiov->kiov_len;
517                 int            msgflg = MSG_DONTWAIT;
518
519                 CDEBUG(D_NET, "page %p + offset %x for %d\n",
520                                page, offset, kiov->kiov_len);
521
522                 if (!cfs_list_empty(&conn->ksnc_tx_queue) ||
523                     fragsize < tx->tx_resid)
524                         msgflg |= MSG_MORE;
525
526                 if (sk->sk_prot->sendpage != NULL) {
527                         rc = sk->sk_prot->sendpage(sk, page,
528                                                    offset, fragsize, msgflg);
529                 } else {
530                         rc = cfs_tcp_sendpage(sk, page, offset, fragsize,
531                                               msgflg);
532                 }
533         } else {
534 #if SOCKNAL_SINGLE_FRAG_TX || !SOCKNAL_RISK_KMAP_DEADLOCK
535                 struct iovec  scratch;
536                 struct iovec *scratchiov = &scratch;
537                 unsigned int  niov = 1;
538 #else
539 #ifdef CONFIG_HIGHMEM
540 #warning "XXX risk of kmap deadlock on multiple frags..."
541 #endif
542                 struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
543                 unsigned int  niov = tx->tx_nkiov;
544 #endif
545                 struct msghdr msg = {
546                         .msg_name       = NULL,
547                         .msg_namelen    = 0,
548                         .msg_iov        = scratchiov,
549                         .msg_iovlen     = niov,
550                         .msg_control    = NULL,
551                         .msg_controllen = 0,
552                         .msg_flags      = MSG_DONTWAIT
553                 };
554                 mm_segment_t  oldmm = get_fs();
555                 int           i;
556
557                 for (nob = i = 0; i < niov; i++) {
558                         scratchiov[i].iov_base = kmap(kiov[i].kiov_page) +
559                                                  kiov[i].kiov_offset;
560                         nob += scratchiov[i].iov_len = kiov[i].kiov_len;
561                 }
562
563                 if (!cfs_list_empty(&conn->ksnc_tx_queue) ||
564                     nob < tx->tx_resid)
565                         msg.msg_flags |= MSG_MORE;
566
567                 set_fs (KERNEL_DS);
568                 rc = sock_sendmsg(sock, &msg, nob);
569                 set_fs (oldmm);
570
571                 for (i = 0; i < niov; i++)
572                         kunmap(kiov[i].kiov_page);
573         }
574         return rc;
575 }
576
577 void
578 ksocknal_lib_eager_ack (ksock_conn_t *conn)
579 {
580         int            opt = 1;
581         mm_segment_t   oldmm = get_fs();
582         struct socket *sock = conn->ksnc_sock;
583
584         /* Remind the socket to ACK eagerly.  If I don't, the socket might
585          * think I'm about to send something it could piggy-back the ACK
586          * on, introducing delay in completing zero-copy sends in my
587          * peer. */
588
589         set_fs(KERNEL_DS);
590         sock->ops->setsockopt (sock, SOL_TCP, TCP_QUICKACK,
591                                (char *)&opt, sizeof (opt));
592         set_fs(oldmm);
593 }
594
595 int
596 ksocknal_lib_recv_iov (ksock_conn_t *conn)
597 {
598 #if SOCKNAL_SINGLE_FRAG_RX
599         struct iovec  scratch;
600         struct iovec *scratchiov = &scratch;
601         unsigned int  niov = 1;
602 #else
603         struct iovec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
604         unsigned int  niov = conn->ksnc_rx_niov;
605 #endif
606         struct iovec *iov = conn->ksnc_rx_iov;
607         struct msghdr msg = {
608                 .msg_name       = NULL,
609                 .msg_namelen    = 0,
610                 .msg_iov        = scratchiov,
611                 .msg_iovlen     = niov,
612                 .msg_control    = NULL,
613                 .msg_controllen = 0,
614                 .msg_flags      = 0
615         };
616         mm_segment_t oldmm = get_fs();
617         int          nob;
618         int          i;
619         int          rc;
620         int          fragnob;
621         int          sum;
622         __u32        saved_csum;
623
624         /* NB we can't trust socket ops to either consume our iovs
625          * or leave them alone. */
626         LASSERT (niov > 0);
627
628         for (nob = i = 0; i < niov; i++) {
629                 scratchiov[i] = iov[i];
630                 nob += scratchiov[i].iov_len;
631         }
632         LASSERT (nob <= conn->ksnc_rx_nob_wanted);
633
634         set_fs (KERNEL_DS);
635         rc = sock_recvmsg (conn->ksnc_sock, &msg, nob, MSG_DONTWAIT);
636         /* NB this is just a boolean..........................^ */
637         set_fs (oldmm);
638
639         saved_csum = 0;
640         if (conn->ksnc_proto == &ksocknal_protocol_v2x) {
641                 saved_csum = conn->ksnc_msg.ksm_csum;
642                 conn->ksnc_msg.ksm_csum = 0;
643         }
644
645         if (saved_csum != 0) {
646                 /* accumulate checksum */
647                 for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) {
648                         LASSERT (i < niov);
649
650                         fragnob = iov[i].iov_len;
651                         if (fragnob > sum)
652                                 fragnob = sum;
653
654                         conn->ksnc_rx_csum = ksocknal_csum(conn->ksnc_rx_csum,
655                                                            iov[i].iov_base, fragnob);
656                 }
657                 conn->ksnc_msg.ksm_csum = saved_csum;
658         }
659
660         return rc;
661 }
662
663 static void
664 ksocknal_lib_kiov_vunmap(void *addr)
665 {
666         if (addr == NULL)
667                 return;
668
669         vunmap(addr);
670 }
671
672 static void *
673 ksocknal_lib_kiov_vmap(lnet_kiov_t *kiov, int niov,
674                        struct iovec *iov, struct page **pages)
675 {
676         void             *addr;
677         int               nob;
678         int               i;
679
680         if (!*ksocknal_tunables.ksnd_zc_recv || pages == NULL)
681                 return NULL;
682
683         LASSERT (niov <= LNET_MAX_IOV);
684
685         if (niov < 2 ||
686             niov < *ksocknal_tunables.ksnd_zc_recv_min_nfrags)
687                 return NULL;
688
689         for (nob = i = 0; i < niov; i++) {
690                 if ((kiov[i].kiov_offset != 0 && i > 0) ||
691                     (kiov[i].kiov_offset + kiov[i].kiov_len != CFS_PAGE_SIZE && i < niov - 1))
692                         return NULL;
693
694                 pages[i] = kiov[i].kiov_page;
695                 nob += kiov[i].kiov_len;
696         }
697
698         addr = vmap(pages, niov, VM_MAP, PAGE_KERNEL);
699         if (addr == NULL)
700                 return NULL;
701
702         iov->iov_base = addr + kiov[0].kiov_offset;
703         iov->iov_len = nob;
704
705         return addr;
706 }
707
708 int
709 ksocknal_lib_recv_kiov (ksock_conn_t *conn)
710 {
711 #if SOCKNAL_SINGLE_FRAG_RX || !SOCKNAL_RISK_KMAP_DEADLOCK
712         struct iovec   scratch;
713         struct iovec  *scratchiov = &scratch;
714         struct page  **pages      = NULL;
715         unsigned int   niov       = 1;
716 #else
717 #ifdef CONFIG_HIGHMEM
718 #warning "XXX risk of kmap deadlock on multiple frags..."
719 #endif
720         struct iovec  *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
721         struct page  **pages      = conn->ksnc_scheduler->kss_rx_scratch_pgs;
722         unsigned int   niov       = conn->ksnc_rx_nkiov;
723 #endif
724         lnet_kiov_t   *kiov = conn->ksnc_rx_kiov;
725         struct msghdr msg = {
726                 .msg_name       = NULL,
727                 .msg_namelen    = 0,
728                 .msg_iov        = scratchiov,
729                 .msg_control    = NULL,
730                 .msg_controllen = 0,
731                 .msg_flags      = 0
732         };
733         mm_segment_t oldmm = get_fs();
734         int          nob;
735         int          i;
736         int          rc;
737         void        *base;
738         void        *addr;
739         int          sum;
740         int          fragnob;
741
742         /* NB we can't trust socket ops to either consume our iovs
743          * or leave them alone. */
744         if ((addr = ksocknal_lib_kiov_vmap(kiov, niov, scratchiov, pages)) != NULL) {
745                 nob = scratchiov[0].iov_len;
746                 msg.msg_iovlen = 1;
747
748         } else {
749                 for (nob = i = 0; i < niov; i++) {
750                         nob += scratchiov[i].iov_len = kiov[i].kiov_len;
751                         scratchiov[i].iov_base = kmap(kiov[i].kiov_page) +
752                                                  kiov[i].kiov_offset;
753                 }
754                 msg.msg_iovlen = niov;
755         }
756
757         LASSERT (nob <= conn->ksnc_rx_nob_wanted);
758
759         set_fs (KERNEL_DS);
760         rc = sock_recvmsg (conn->ksnc_sock, &msg, nob, MSG_DONTWAIT);
761         /* NB this is just a boolean.......................^ */
762         set_fs (oldmm);
763
764         if (conn->ksnc_msg.ksm_csum != 0) {
765                 for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) {
766                         LASSERT (i < niov);
767
768                         /* Dang! have to kmap again because I have nowhere to stash the
769                          * mapped address.  But by doing it while the page is still
770                          * mapped, the kernel just bumps the map count and returns me
771                          * the address it stashed. */
772                         base = kmap(kiov[i].kiov_page) + kiov[i].kiov_offset;
773                         fragnob = kiov[i].kiov_len;
774                         if (fragnob > sum)
775                                 fragnob = sum;
776
777                         conn->ksnc_rx_csum = ksocknal_csum(conn->ksnc_rx_csum,
778                                                            base, fragnob);
779
780                         kunmap(kiov[i].kiov_page);
781                 }
782         }
783
784         if (addr != NULL) {
785                 ksocknal_lib_kiov_vunmap(addr);
786         } else {
787                 for (i = 0; i < niov; i++)
788                         kunmap(kiov[i].kiov_page);
789         }
790
791         return (rc);
792 }
793
794 void
795 ksocknal_lib_csum_tx(ksock_tx_t *tx)
796 {
797         int          i;
798         __u32        csum;
799         void        *base;
800
801         LASSERT(tx->tx_iov[0].iov_base == (void *)&tx->tx_msg);
802         LASSERT(tx->tx_conn != NULL);
803         LASSERT(tx->tx_conn->ksnc_proto == &ksocknal_protocol_v2x);
804
805         tx->tx_msg.ksm_csum = 0;
806
807         csum = ksocknal_csum(~0, (void *)tx->tx_iov[0].iov_base,
808                              tx->tx_iov[0].iov_len);
809
810         if (tx->tx_kiov != NULL) {
811                 for (i = 0; i < tx->tx_nkiov; i++) {
812                         base = kmap(tx->tx_kiov[i].kiov_page) +
813                                tx->tx_kiov[i].kiov_offset;
814
815                         csum = ksocknal_csum(csum, base, tx->tx_kiov[i].kiov_len);
816
817                         kunmap(tx->tx_kiov[i].kiov_page);
818                 }
819         } else {
820                 for (i = 1; i < tx->tx_niov; i++)
821                         csum = ksocknal_csum(csum, tx->tx_iov[i].iov_base,
822                                              tx->tx_iov[i].iov_len);
823         }
824
825         if (*ksocknal_tunables.ksnd_inject_csum_error) {
826                 csum++;
827                 *ksocknal_tunables.ksnd_inject_csum_error = 0;
828         }
829
830         tx->tx_msg.ksm_csum = csum;
831 }
832
833 int
834 ksocknal_lib_get_conn_tunables (ksock_conn_t *conn, int *txmem, int *rxmem, int *nagle)
835 {
836         mm_segment_t   oldmm = get_fs ();
837         struct socket *sock = conn->ksnc_sock;
838         int            len;
839         int            rc;
840
841         rc = ksocknal_connsock_addref(conn);
842         if (rc != 0) {
843                 LASSERT (conn->ksnc_closing);
844                 *txmem = *rxmem = *nagle = 0;
845                 return (-ESHUTDOWN);
846         }
847
848         rc = libcfs_sock_getbuf(sock, txmem, rxmem);
849         if (rc == 0) {
850                 len = sizeof(*nagle);
851                 set_fs(KERNEL_DS);
852                 rc = sock->ops->getsockopt(sock, SOL_TCP, TCP_NODELAY,
853                                            (char *)nagle, &len);
854                 set_fs(oldmm);
855         }
856
857         ksocknal_connsock_decref(conn);
858
859         if (rc == 0)
860                 *nagle = !*nagle;
861         else
862                 *txmem = *rxmem = *nagle = 0;
863
864         return (rc);
865 }
866
867 int
868 ksocknal_lib_setup_sock (struct socket *sock)
869 {
870         mm_segment_t    oldmm = get_fs ();
871         int             rc;
872         int             option;
873         int             keep_idle;
874         int             keep_intvl;
875         int             keep_count;
876         int             do_keepalive;
877         struct linger   linger;
878
879         sock->sk->sk_allocation = GFP_NOFS;
880
881         /* Ensure this socket aborts active sends immediately when we close
882          * it. */
883
884         linger.l_onoff = 0;
885         linger.l_linger = 0;
886
887         set_fs (KERNEL_DS);
888         rc = sock_setsockopt (sock, SOL_SOCKET, SO_LINGER,
889                               (char *)&linger, sizeof (linger));
890         set_fs (oldmm);
891         if (rc != 0) {
892                 CERROR ("Can't set SO_LINGER: %d\n", rc);
893                 return (rc);
894         }
895
896         option = -1;
897         set_fs (KERNEL_DS);
898         rc = sock->ops->setsockopt (sock, SOL_TCP, TCP_LINGER2,
899                                     (char *)&option, sizeof (option));
900         set_fs (oldmm);
901         if (rc != 0) {
902                 CERROR ("Can't set SO_LINGER2: %d\n", rc);
903                 return (rc);
904         }
905
906         if (!*ksocknal_tunables.ksnd_nagle) {
907                 option = 1;
908
909                 set_fs (KERNEL_DS);
910                 rc = sock->ops->setsockopt (sock, SOL_TCP, TCP_NODELAY,
911                                             (char *)&option, sizeof (option));
912                 set_fs (oldmm);
913                 if (rc != 0) {
914                         CERROR ("Can't disable nagle: %d\n", rc);
915                         return (rc);
916                 }
917         }
918
919         rc = libcfs_sock_setbuf(sock,
920                                 *ksocknal_tunables.ksnd_tx_buffer_size,
921                                 *ksocknal_tunables.ksnd_rx_buffer_size);
922         if (rc != 0) {
923                 CERROR ("Can't set buffer tx %d, rx %d buffers: %d\n",
924                         *ksocknal_tunables.ksnd_tx_buffer_size,
925                         *ksocknal_tunables.ksnd_rx_buffer_size, rc);
926                 return (rc);
927         }
928
929 /* TCP_BACKOFF_* sockopt tunables unsupported in stock kernels */
930 #ifdef SOCKNAL_BACKOFF
931         if (*ksocknal_tunables.ksnd_backoff_init > 0) {
932                 option = *ksocknal_tunables.ksnd_backoff_init;
933 #ifdef SOCKNAL_BACKOFF_MS
934                 option *= 1000;
935 #endif
936
937                 set_fs (KERNEL_DS);
938                 rc = sock->ops->setsockopt (sock, SOL_TCP, TCP_BACKOFF_INIT,
939                                             (char *)&option, sizeof (option));
940                 set_fs (oldmm);
941                 if (rc != 0) {
942                         CERROR ("Can't set initial tcp backoff %d: %d\n",
943                                 option, rc);
944                         return (rc);
945                 }
946         }
947
948         if (*ksocknal_tunables.ksnd_backoff_max > 0) {
949                 option = *ksocknal_tunables.ksnd_backoff_max;
950 #ifdef SOCKNAL_BACKOFF_MS
951                 option *= 1000;
952 #endif
953
954                 set_fs (KERNEL_DS);
955                 rc = sock->ops->setsockopt (sock, SOL_TCP, TCP_BACKOFF_MAX,
956                                             (char *)&option, sizeof (option));
957                 set_fs (oldmm);
958                 if (rc != 0) {
959                         CERROR ("Can't set maximum tcp backoff %d: %d\n",
960                                 option, rc);
961                         return (rc);
962                 }
963         }
964 #endif
965
966         /* snapshot tunables */
967         keep_idle  = *ksocknal_tunables.ksnd_keepalive_idle;
968         keep_count = *ksocknal_tunables.ksnd_keepalive_count;
969         keep_intvl = *ksocknal_tunables.ksnd_keepalive_intvl;
970
971         do_keepalive = (keep_idle > 0 && keep_count > 0 && keep_intvl > 0);
972
973         option = (do_keepalive ? 1 : 0);
974         set_fs (KERNEL_DS);
975         rc = sock_setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE,
976                               (char *)&option, sizeof (option));
977         set_fs (oldmm);
978         if (rc != 0) {
979                 CERROR ("Can't set SO_KEEPALIVE: %d\n", rc);
980                 return (rc);
981         }
982
983         if (!do_keepalive)
984                 return (0);
985
986         set_fs (KERNEL_DS);
987         rc = sock->ops->setsockopt (sock, SOL_TCP, TCP_KEEPIDLE,
988                                     (char *)&keep_idle, sizeof (keep_idle));
989         set_fs (oldmm);
990         if (rc != 0) {
991                 CERROR ("Can't set TCP_KEEPIDLE: %d\n", rc);
992                 return (rc);
993         }
994
995         set_fs (KERNEL_DS);
996         rc = sock->ops->setsockopt (sock, SOL_TCP, TCP_KEEPINTVL,
997                                     (char *)&keep_intvl, sizeof (keep_intvl));
998         set_fs (oldmm);
999         if (rc != 0) {
1000                 CERROR ("Can't set TCP_KEEPINTVL: %d\n", rc);
1001                 return (rc);
1002         }
1003
1004         set_fs (KERNEL_DS);
1005         rc = sock->ops->setsockopt (sock, SOL_TCP, TCP_KEEPCNT,
1006                                     (char *)&keep_count, sizeof (keep_count));
1007         set_fs (oldmm);
1008         if (rc != 0) {
1009                 CERROR ("Can't set TCP_KEEPCNT: %d\n", rc);
1010                 return (rc);
1011         }
1012
1013         return (0);
1014 }
1015
1016 void
1017 ksocknal_lib_push_conn (ksock_conn_t *conn)
1018 {
1019         struct sock    *sk;
1020         struct tcp_sock *tp;
1021         int             nonagle;
1022         int             val = 1;
1023         int             rc;
1024         mm_segment_t    oldmm;
1025
1026         rc = ksocknal_connsock_addref(conn);
1027         if (rc != 0)                            /* being shut down */
1028                 return;
1029
1030         sk = conn->ksnc_sock->sk;
1031         tp = tcp_sk(sk);
1032
1033         lock_sock (sk);
1034         nonagle = tp->nonagle;
1035         tp->nonagle = 1;
1036         release_sock (sk);
1037
1038         oldmm = get_fs ();
1039         set_fs (KERNEL_DS);
1040
1041         rc = sk->sk_prot->setsockopt (sk, SOL_TCP, TCP_NODELAY,
1042                                       (char *)&val, sizeof (val));
1043         LASSERT (rc == 0);
1044
1045         set_fs (oldmm);
1046
1047         lock_sock (sk);
1048         tp->nonagle = nonagle;
1049         release_sock (sk);
1050
1051         ksocknal_connsock_decref(conn);
1052 }
1053
1054 extern void ksocknal_read_callback (ksock_conn_t *conn);
1055 extern void ksocknal_write_callback (ksock_conn_t *conn);
1056 /*
1057  * socket call back in Linux
1058  */
1059 static void
1060 ksocknal_data_ready (struct sock *sk, int n)
1061 {
1062         ksock_conn_t  *conn;
1063         ENTRY;
1064
1065         /* interleave correctly with closing sockets... */
1066         LASSERT(!in_irq());
1067         read_lock(&ksocknal_data.ksnd_global_lock);
1068
1069         conn = sk->sk_user_data;
1070         if (conn == NULL) {             /* raced with ksocknal_terminate_conn */
1071                 LASSERT (sk->sk_data_ready != &ksocknal_data_ready);
1072                 sk->sk_data_ready (sk, n);
1073         } else
1074                 ksocknal_read_callback(conn);
1075
1076         read_unlock(&ksocknal_data.ksnd_global_lock);
1077
1078         EXIT;
1079 }
1080
1081 static void
1082 ksocknal_write_space (struct sock *sk)
1083 {
1084         ksock_conn_t  *conn;
1085         int            wspace;
1086         int            min_wpace;
1087
1088         /* interleave correctly with closing sockets... */
1089         LASSERT(!in_irq());
1090         read_lock(&ksocknal_data.ksnd_global_lock);
1091
1092         conn = sk->sk_user_data;
1093         wspace = SOCKNAL_WSPACE(sk);
1094         min_wpace = SOCKNAL_MIN_WSPACE(sk);
1095
1096         CDEBUG(D_NET, "sk %p wspace %d low water %d conn %p%s%s%s\n",
1097                sk, wspace, min_wpace, conn,
1098                (conn == NULL) ? "" : (conn->ksnc_tx_ready ?
1099                                       " ready" : " blocked"),
1100                (conn == NULL) ? "" : (conn->ksnc_tx_scheduled ?
1101                                       " scheduled" : " idle"),
1102                (conn == NULL) ? "" : (cfs_list_empty (&conn->ksnc_tx_queue) ?
1103                                       " empty" : " queued"));
1104
1105         if (conn == NULL) {             /* raced with ksocknal_terminate_conn */
1106                 LASSERT (sk->sk_write_space != &ksocknal_write_space);
1107                 sk->sk_write_space (sk);
1108
1109                 read_unlock(&ksocknal_data.ksnd_global_lock);
1110                 return;
1111         }
1112
1113         if (wspace >= min_wpace) {              /* got enough space */
1114                 ksocknal_write_callback(conn);
1115
1116                 /* Clear SOCK_NOSPACE _after_ ksocknal_write_callback so the
1117                  * ENOMEM check in ksocknal_transmit is race-free (think about
1118                  * it). */
1119
1120                 clear_bit (SOCK_NOSPACE, &sk->sk_socket->flags);
1121         }
1122
1123         read_unlock(&ksocknal_data.ksnd_global_lock);
1124 }
1125
1126 void
1127 ksocknal_lib_save_callback(struct socket *sock, ksock_conn_t *conn)
1128 {
1129         conn->ksnc_saved_data_ready = sock->sk->sk_data_ready;
1130         conn->ksnc_saved_write_space = sock->sk->sk_write_space;
1131 }
1132
1133 void
1134 ksocknal_lib_set_callback(struct socket *sock,  ksock_conn_t *conn)
1135 {
1136         sock->sk->sk_user_data = conn;
1137         sock->sk->sk_data_ready = ksocknal_data_ready;
1138         sock->sk->sk_write_space = ksocknal_write_space;
1139         return;
1140 }
1141
1142 void
1143 ksocknal_lib_reset_callback(struct socket *sock, ksock_conn_t *conn)
1144 {
1145         /* Remove conn's network callbacks.
1146          * NB I _have_ to restore the callback, rather than storing a noop,
1147          * since the socket could survive past this module being unloaded!! */
1148         sock->sk->sk_data_ready = conn->ksnc_saved_data_ready;
1149         sock->sk->sk_write_space = conn->ksnc_saved_write_space;
1150
1151         /* A callback could be in progress already; they hold a read lock
1152          * on ksnd_global_lock (to serialise with me) and NOOP if
1153          * sk_user_data is NULL. */
1154         sock->sk->sk_user_data = NULL;
1155
1156         return ;
1157 }
1158
1159 int
1160 ksocknal_lib_memory_pressure(ksock_conn_t *conn)
1161 {
1162         int            rc = 0;
1163         ksock_sched_t *sched;
1164
1165         sched = conn->ksnc_scheduler;
1166         spin_lock_bh(&sched->kss_lock);
1167
1168         if (!SOCK_TEST_NOSPACE(conn->ksnc_sock) &&
1169             !conn->ksnc_tx_ready) {
1170                 /* SOCK_NOSPACE is set when the socket fills
1171                  * and cleared in the write_space callback
1172                  * (which also sets ksnc_tx_ready).  If
1173                  * SOCK_NOSPACE and ksnc_tx_ready are BOTH
1174                  * zero, I didn't fill the socket and
1175                  * write_space won't reschedule me, so I
1176                  * return -ENOMEM to get my caller to retry
1177                  * after a timeout */
1178                 rc = -ENOMEM;
1179         }
1180
1181         spin_unlock_bh(&sched->kss_lock);
1182
1183         return rc;
1184 }