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