Whamcloud - gitweb
LU-4423 socklnd: use kernel socket sockopt apis
[fs/lustre-release.git] / lnet / klnds / socklnd / socklnd_lib.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 = lnet_sock_getaddr(conn->ksnc_sock, true,
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 = lnet_sock_getaddr(conn->ksnc_sock, false,
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 kvec scratch;
402                 struct kvec *scratchiov = &scratch;
403                 unsigned int niov = 1;
404 #else
405                 struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
406                 unsigned int niov = tx->tx_niov;
407 #endif
408                 struct msghdr msg = { .msg_flags = MSG_DONTWAIT };
409                 int  i;
410
411                 for (nob = i = 0; i < niov; i++) {
412                         scratchiov[i] = tx->tx_iov[i];
413                         nob += scratchiov[i].iov_len;
414                 }
415
416                 if (!list_empty(&conn->ksnc_tx_queue) ||
417                     nob < tx->tx_resid)
418                         msg.msg_flags |= MSG_MORE;
419
420                 rc = kernel_sendmsg(sock, &msg, scratchiov, niov, nob);
421         }
422         return rc;
423 }
424
425 int
426 ksocknal_lib_send_kiov(ksock_conn_t *conn, ksock_tx_t *tx)
427 {
428         struct socket *sock = conn->ksnc_sock;
429         lnet_kiov_t   *kiov = tx->tx_kiov;
430         int            rc;
431         int            nob;
432
433         /* Not NOOP message */
434         LASSERT (tx->tx_lnetmsg != NULL);
435
436         /* NB we can't trust socket ops to either consume our iovs
437          * or leave them alone. */
438         if (tx->tx_msg.ksm_zc_cookies[0] != 0) {
439                 /* Zero copy is enabled */
440                 struct sock   *sk = sock->sk;
441                 struct page   *page = kiov->kiov_page;
442                 int            offset = kiov->kiov_offset;
443                 int            fragsize = kiov->kiov_len;
444                 int            msgflg = MSG_DONTWAIT;
445
446                 CDEBUG(D_NET, "page %p + offset %x for %d\n",
447                                page, offset, kiov->kiov_len);
448
449                 if (!list_empty(&conn->ksnc_tx_queue) ||
450                     fragsize < tx->tx_resid)
451                         msgflg |= MSG_MORE;
452
453                 if (sk->sk_prot->sendpage != NULL) {
454                         rc = sk->sk_prot->sendpage(sk, page,
455                                                    offset, fragsize, msgflg);
456                 } else {
457                         rc = cfs_tcp_sendpage(sk, page, offset, fragsize,
458                                               msgflg);
459                 }
460         } else {
461 #if SOCKNAL_SINGLE_FRAG_TX || !SOCKNAL_RISK_KMAP_DEADLOCK
462                 struct kvec     scratch;
463                 struct kvec   *scratchiov = &scratch;
464                 unsigned int    niov = 1;
465 #else
466 #ifdef CONFIG_HIGHMEM
467 #warning "XXX risk of kmap deadlock on multiple frags..."
468 #endif
469                 struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
470                 unsigned int  niov = tx->tx_nkiov;
471 #endif
472                 struct msghdr msg = { .msg_flags = MSG_DONTWAIT };
473                 int           i;
474
475                 for (nob = i = 0; i < niov; i++) {
476                         scratchiov[i].iov_base = kmap(kiov[i].kiov_page) +
477                                                  kiov[i].kiov_offset;
478                         nob += scratchiov[i].iov_len = kiov[i].kiov_len;
479                 }
480
481                 if (!list_empty(&conn->ksnc_tx_queue) ||
482                     nob < tx->tx_resid)
483                         msg.msg_flags |= MSG_MORE;
484
485                 rc = kernel_sendmsg(sock, &msg, scratchiov, niov, nob);
486
487                 for (i = 0; i < niov; i++)
488                         kunmap(kiov[i].kiov_page);
489         }
490         return rc;
491 }
492
493 void
494 ksocknal_lib_eager_ack (ksock_conn_t *conn)
495 {
496         int            opt = 1;
497         struct socket *sock = conn->ksnc_sock;
498
499         /* Remind the socket to ACK eagerly.  If I don't, the socket might
500          * think I'm about to send something it could piggy-back the ACK
501          * on, introducing delay in completing zero-copy sends in my
502          * peer. */
503
504         kernel_setsockopt(sock, SOL_TCP, TCP_QUICKACK,
505                           (char *)&opt, sizeof(opt));
506 }
507
508 int
509 ksocknal_lib_recv_iov (ksock_conn_t *conn)
510 {
511 #if SOCKNAL_SINGLE_FRAG_RX
512         struct kvec  scratch;
513         struct kvec *scratchiov = &scratch;
514         unsigned int  niov = 1;
515 #else
516         struct kvec *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
517         unsigned int  niov = conn->ksnc_rx_niov;
518 #endif
519         struct kvec *iov = conn->ksnc_rx_iov;
520         struct msghdr msg = {
521                 .msg_flags      = 0
522         };
523         int          nob;
524         int          i;
525         int          rc;
526         int          fragnob;
527         int          sum;
528         __u32        saved_csum;
529
530         /* NB we can't trust socket ops to either consume our iovs
531          * or leave them alone. */
532         LASSERT (niov > 0);
533
534         for (nob = i = 0; i < niov; i++) {
535                 scratchiov[i] = iov[i];
536                 nob += scratchiov[i].iov_len;
537         }
538         LASSERT (nob <= conn->ksnc_rx_nob_wanted);
539
540         rc = kernel_recvmsg(conn->ksnc_sock, &msg, scratchiov, niov, nob,
541                             MSG_DONTWAIT);
542
543         saved_csum = 0;
544         if (conn->ksnc_proto == &ksocknal_protocol_v2x) {
545                 saved_csum = conn->ksnc_msg.ksm_csum;
546                 conn->ksnc_msg.ksm_csum = 0;
547         }
548
549         if (saved_csum != 0) {
550                 /* accumulate checksum */
551                 for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) {
552                         LASSERT (i < niov);
553
554                         fragnob = iov[i].iov_len;
555                         if (fragnob > sum)
556                                 fragnob = sum;
557
558                         conn->ksnc_rx_csum = ksocknal_csum(conn->ksnc_rx_csum,
559                                                            iov[i].iov_base, fragnob);
560                 }
561                 conn->ksnc_msg.ksm_csum = saved_csum;
562         }
563
564         return rc;
565 }
566
567 static void
568 ksocknal_lib_kiov_vunmap(void *addr)
569 {
570         if (addr == NULL)
571                 return;
572
573         vunmap(addr);
574 }
575
576 static void *
577 ksocknal_lib_kiov_vmap(lnet_kiov_t *kiov, int niov,
578                        struct kvec *iov, struct page **pages)
579 {
580         void             *addr;
581         int               nob;
582         int               i;
583
584         if (!*ksocknal_tunables.ksnd_zc_recv || pages == NULL)
585                 return NULL;
586
587         LASSERT (niov <= LNET_MAX_IOV);
588
589         if (niov < 2 ||
590             niov < *ksocknal_tunables.ksnd_zc_recv_min_nfrags)
591                 return NULL;
592
593         for (nob = i = 0; i < niov; i++) {
594                 if ((kiov[i].kiov_offset != 0 && i > 0) ||
595                     (kiov[i].kiov_offset + kiov[i].kiov_len !=
596                      PAGE_CACHE_SIZE && i < niov - 1))
597                         return NULL;
598
599                 pages[i] = kiov[i].kiov_page;
600                 nob += kiov[i].kiov_len;
601         }
602
603         addr = vmap(pages, niov, VM_MAP, PAGE_KERNEL);
604         if (addr == NULL)
605                 return NULL;
606
607         iov->iov_base = addr + kiov[0].kiov_offset;
608         iov->iov_len = nob;
609
610         return addr;
611 }
612
613 int
614 ksocknal_lib_recv_kiov (ksock_conn_t *conn)
615 {
616 #if SOCKNAL_SINGLE_FRAG_RX || !SOCKNAL_RISK_KMAP_DEADLOCK
617         struct kvec   scratch;
618         struct kvec  *scratchiov = &scratch;
619         struct page  **pages      = NULL;
620         unsigned int   niov       = 1;
621 #else
622 #ifdef CONFIG_HIGHMEM
623 #warning "XXX risk of kmap deadlock on multiple frags..."
624 #endif
625         struct kvec  *scratchiov = conn->ksnc_scheduler->kss_scratch_iov;
626         struct page  **pages      = conn->ksnc_scheduler->kss_rx_scratch_pgs;
627         unsigned int   niov       = conn->ksnc_rx_nkiov;
628 #endif
629         lnet_kiov_t   *kiov = conn->ksnc_rx_kiov;
630         struct msghdr msg = {
631                 .msg_flags      = 0
632         };
633         int          nob;
634         int          i;
635         int          rc;
636         void        *base;
637         void        *addr;
638         int          sum;
639         int          fragnob;
640         int n;
641
642         /* NB we can't trust socket ops to either consume our iovs
643          * or leave them alone. */
644         if ((addr = ksocknal_lib_kiov_vmap(kiov, niov, scratchiov, pages)) != NULL) {
645                 nob = scratchiov[0].iov_len;
646                 n = 1;
647
648         } else {
649                 for (nob = i = 0; i < niov; i++) {
650                         nob += scratchiov[i].iov_len = kiov[i].kiov_len;
651                         scratchiov[i].iov_base = kmap(kiov[i].kiov_page) +
652                                                  kiov[i].kiov_offset;
653                 }
654                 n = niov;
655         }
656
657         LASSERT (nob <= conn->ksnc_rx_nob_wanted);
658
659         rc = kernel_recvmsg(conn->ksnc_sock, &msg, scratchiov, n, nob,
660                             MSG_DONTWAIT);
661
662         if (conn->ksnc_msg.ksm_csum != 0) {
663                 for (i = 0, sum = rc; sum > 0; i++, sum -= fragnob) {
664                         LASSERT (i < niov);
665
666                         /* Dang! have to kmap again because I have nowhere to stash the
667                          * mapped address.  But by doing it while the page is still
668                          * mapped, the kernel just bumps the map count and returns me
669                          * the address it stashed. */
670                         base = kmap(kiov[i].kiov_page) + kiov[i].kiov_offset;
671                         fragnob = kiov[i].kiov_len;
672                         if (fragnob > sum)
673                                 fragnob = sum;
674
675                         conn->ksnc_rx_csum = ksocknal_csum(conn->ksnc_rx_csum,
676                                                            base, fragnob);
677
678                         kunmap(kiov[i].kiov_page);
679                 }
680         }
681
682         if (addr != NULL) {
683                 ksocknal_lib_kiov_vunmap(addr);
684         } else {
685                 for (i = 0; i < niov; i++)
686                         kunmap(kiov[i].kiov_page);
687         }
688
689         return (rc);
690 }
691
692 void
693 ksocknal_lib_csum_tx(ksock_tx_t *tx)
694 {
695         int          i;
696         __u32        csum;
697         void        *base;
698
699         LASSERT(tx->tx_iov[0].iov_base == (void *)&tx->tx_msg);
700         LASSERT(tx->tx_conn != NULL);
701         LASSERT(tx->tx_conn->ksnc_proto == &ksocknal_protocol_v2x);
702
703         tx->tx_msg.ksm_csum = 0;
704
705         csum = ksocknal_csum(~0, (void *)tx->tx_iov[0].iov_base,
706                              tx->tx_iov[0].iov_len);
707
708         if (tx->tx_kiov != NULL) {
709                 for (i = 0; i < tx->tx_nkiov; i++) {
710                         base = kmap(tx->tx_kiov[i].kiov_page) +
711                                tx->tx_kiov[i].kiov_offset;
712
713                         csum = ksocknal_csum(csum, base, tx->tx_kiov[i].kiov_len);
714
715                         kunmap(tx->tx_kiov[i].kiov_page);
716                 }
717         } else {
718                 for (i = 1; i < tx->tx_niov; i++)
719                         csum = ksocknal_csum(csum, tx->tx_iov[i].iov_base,
720                                              tx->tx_iov[i].iov_len);
721         }
722
723         if (*ksocknal_tunables.ksnd_inject_csum_error) {
724                 csum++;
725                 *ksocknal_tunables.ksnd_inject_csum_error = 0;
726         }
727
728         tx->tx_msg.ksm_csum = csum;
729 }
730
731 int
732 ksocknal_lib_get_conn_tunables (ksock_conn_t *conn, int *txmem, int *rxmem, int *nagle)
733 {
734         struct socket *sock = conn->ksnc_sock;
735         int            len;
736         int            rc;
737
738         rc = ksocknal_connsock_addref(conn);
739         if (rc != 0) {
740                 LASSERT (conn->ksnc_closing);
741                 *txmem = *rxmem = *nagle = 0;
742                 return (-ESHUTDOWN);
743         }
744
745         rc = lnet_sock_getbuf(sock, txmem, rxmem);
746         if (rc == 0) {
747                 len = sizeof(*nagle);
748                 rc = kernel_getsockopt(sock, SOL_TCP, TCP_NODELAY,
749                                        (char *)nagle, &len);
750         }
751
752         ksocknal_connsock_decref(conn);
753
754         if (rc == 0)
755                 *nagle = !*nagle;
756         else
757                 *txmem = *rxmem = *nagle = 0;
758
759         return (rc);
760 }
761
762 int
763 ksocknal_lib_setup_sock (struct socket *sock)
764 {
765         int             rc;
766         int             option;
767         int             keep_idle;
768         int             keep_intvl;
769         int             keep_count;
770         int             do_keepalive;
771         struct linger   linger;
772
773         sock->sk->sk_allocation = GFP_NOFS;
774
775         /* Ensure this socket aborts active sends immediately when we close
776          * it. */
777
778         linger.l_onoff = 0;
779         linger.l_linger = 0;
780
781         rc = kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER,
782                                (char *)&linger, sizeof(linger));
783         if (rc != 0) {
784                 CERROR ("Can't set SO_LINGER: %d\n", rc);
785                 return (rc);
786         }
787
788         option = -1;
789         rc = kernel_setsockopt(sock, SOL_TCP, TCP_LINGER2,
790                                (char *)&option, sizeof(option));
791         if (rc != 0) {
792                 CERROR ("Can't set SO_LINGER2: %d\n", rc);
793                 return (rc);
794         }
795
796         if (!*ksocknal_tunables.ksnd_nagle) {
797                 option = 1;
798
799                 rc = kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY,
800                                        (char *)&option, sizeof(option));
801                 if (rc != 0) {
802                         CERROR ("Can't disable nagle: %d\n", rc);
803                         return (rc);
804                 }
805         }
806
807         rc = lnet_sock_setbuf(sock,
808                               *ksocknal_tunables.ksnd_tx_buffer_size,
809                               *ksocknal_tunables.ksnd_rx_buffer_size);
810         if (rc != 0) {
811                 CERROR ("Can't set buffer tx %d, rx %d buffers: %d\n",
812                         *ksocknal_tunables.ksnd_tx_buffer_size,
813                         *ksocknal_tunables.ksnd_rx_buffer_size, rc);
814                 return (rc);
815         }
816
817 /* TCP_BACKOFF_* sockopt tunables unsupported in stock kernels */
818 #ifdef SOCKNAL_BACKOFF
819         if (*ksocknal_tunables.ksnd_backoff_init > 0) {
820                 option = *ksocknal_tunables.ksnd_backoff_init;
821 #ifdef SOCKNAL_BACKOFF_MS
822                 option *= 1000;
823 #endif
824
825                 rc = kernel_setsockopt(sock, SOL_TCP, TCP_BACKOFF_INIT,
826                                        (char *)&option, sizeof(option));
827                 if (rc != 0) {
828                         CERROR ("Can't set initial tcp backoff %d: %d\n",
829                                 option, rc);
830                         return (rc);
831                 }
832         }
833
834         if (*ksocknal_tunables.ksnd_backoff_max > 0) {
835                 option = *ksocknal_tunables.ksnd_backoff_max;
836 #ifdef SOCKNAL_BACKOFF_MS
837                 option *= 1000;
838 #endif
839
840                 rc = kernel_setsockopt(sock, SOL_TCP, TCP_BACKOFF_MAX,
841                                        (char *)&option, sizeof(option));
842                 if (rc != 0) {
843                         CERROR ("Can't set maximum tcp backoff %d: %d\n",
844                                 option, rc);
845                         return (rc);
846                 }
847         }
848 #endif
849
850         /* snapshot tunables */
851         keep_idle  = *ksocknal_tunables.ksnd_keepalive_idle;
852         keep_count = *ksocknal_tunables.ksnd_keepalive_count;
853         keep_intvl = *ksocknal_tunables.ksnd_keepalive_intvl;
854
855         do_keepalive = (keep_idle > 0 && keep_count > 0 && keep_intvl > 0);
856
857         option = (do_keepalive ? 1 : 0);
858         rc = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
859                                (char *)&option, sizeof(option));
860         if (rc != 0) {
861                 CERROR ("Can't set SO_KEEPALIVE: %d\n", rc);
862                 return (rc);
863         }
864
865         if (!do_keepalive)
866                 return (0);
867
868         rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE,
869                                (char *)&keep_idle, sizeof(keep_idle));
870         if (rc != 0) {
871                 CERROR ("Can't set TCP_KEEPIDLE: %d\n", rc);
872                 return (rc);
873         }
874
875         rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL,
876                                (char *)&keep_intvl, sizeof(keep_intvl));
877         if (rc != 0) {
878                 CERROR ("Can't set TCP_KEEPINTVL: %d\n", rc);
879                 return (rc);
880         }
881
882         rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
883                                (char *)&keep_count, sizeof(keep_count));
884         if (rc != 0) {
885                 CERROR ("Can't set TCP_KEEPCNT: %d\n", rc);
886                 return (rc);
887         }
888
889         return (0);
890 }
891
892 void
893 ksocknal_lib_push_conn (ksock_conn_t *conn)
894 {
895         struct sock    *sk;
896         struct tcp_sock *tp;
897         int             nonagle;
898         int             val = 1;
899         int             rc;
900
901         rc = ksocknal_connsock_addref(conn);
902         if (rc != 0)                            /* being shut down */
903                 return;
904
905         sk = conn->ksnc_sock->sk;
906         tp = tcp_sk(sk);
907
908         lock_sock (sk);
909         nonagle = tp->nonagle;
910         tp->nonagle = 1;
911         release_sock (sk);
912
913         rc = kernel_setsockopt(conn->ksnc_sock, SOL_TCP, TCP_NODELAY,
914                                (char *)&val, sizeof(val));
915         LASSERT (rc == 0);
916
917         lock_sock (sk);
918         tp->nonagle = nonagle;
919         release_sock (sk);
920
921         ksocknal_connsock_decref(conn);
922 }
923
924 extern void ksocknal_read_callback (ksock_conn_t *conn);
925 extern void ksocknal_write_callback (ksock_conn_t *conn);
926 /*
927  * socket call back in Linux
928  */
929 static void
930 #ifdef HAVE_SK_DATA_READY_ONE_ARG
931 ksocknal_data_ready(struct sock *sk)
932 #else
933 ksocknal_data_ready(struct sock *sk, int n)
934 #endif
935 {
936         ksock_conn_t  *conn;
937         ENTRY;
938
939         /* interleave correctly with closing sockets... */
940         LASSERT(!in_irq());
941         read_lock(&ksocknal_data.ksnd_global_lock);
942
943         conn = sk->sk_user_data;
944         if (conn == NULL) {     /* raced with ksocknal_terminate_conn */
945                 LASSERT(sk->sk_data_ready != &ksocknal_data_ready);
946 #ifdef HAVE_SK_DATA_READY_ONE_ARG
947                 sk->sk_data_ready(sk);
948 #else
949                 sk->sk_data_ready(sk, n);
950 #endif
951         } else
952                 ksocknal_read_callback(conn);
953
954         read_unlock(&ksocknal_data.ksnd_global_lock);
955
956         EXIT;
957 }
958
959 static void
960 ksocknal_write_space (struct sock *sk)
961 {
962         ksock_conn_t  *conn;
963         int            wspace;
964         int            min_wpace;
965
966         /* interleave correctly with closing sockets... */
967         LASSERT(!in_irq());
968         read_lock(&ksocknal_data.ksnd_global_lock);
969
970         conn = sk->sk_user_data;
971         wspace = sk_stream_wspace(sk);
972         min_wpace = sk_stream_min_wspace(sk);
973
974         CDEBUG(D_NET, "sk %p wspace %d low water %d conn %p%s%s%s\n",
975                sk, wspace, min_wpace, conn,
976                (conn == NULL) ? "" : (conn->ksnc_tx_ready ?
977                                       " ready" : " blocked"),
978                (conn == NULL) ? "" : (conn->ksnc_tx_scheduled ?
979                                       " scheduled" : " idle"),
980                (conn == NULL) ? "" : (list_empty(&conn->ksnc_tx_queue) ?
981                                       " empty" : " queued"));
982
983         if (conn == NULL) {             /* raced with ksocknal_terminate_conn */
984                 LASSERT (sk->sk_write_space != &ksocknal_write_space);
985                 sk->sk_write_space (sk);
986
987                 read_unlock(&ksocknal_data.ksnd_global_lock);
988                 return;
989         }
990
991         if (wspace >= min_wpace) {              /* got enough space */
992                 ksocknal_write_callback(conn);
993
994                 /* Clear SOCK_NOSPACE _after_ ksocknal_write_callback so the
995                  * ENOMEM check in ksocknal_transmit is race-free (think about
996                  * it). */
997
998                 clear_bit (SOCK_NOSPACE, &sk->sk_socket->flags);
999         }
1000
1001         read_unlock(&ksocknal_data.ksnd_global_lock);
1002 }
1003
1004 void
1005 ksocknal_lib_save_callback(struct socket *sock, ksock_conn_t *conn)
1006 {
1007         conn->ksnc_saved_data_ready = sock->sk->sk_data_ready;
1008         conn->ksnc_saved_write_space = sock->sk->sk_write_space;
1009 }
1010
1011 void
1012 ksocknal_lib_set_callback(struct socket *sock,  ksock_conn_t *conn)
1013 {
1014         sock->sk->sk_user_data = conn;
1015         sock->sk->sk_data_ready = ksocknal_data_ready;
1016         sock->sk->sk_write_space = ksocknal_write_space;
1017         return;
1018 }
1019
1020 void
1021 ksocknal_lib_reset_callback(struct socket *sock, ksock_conn_t *conn)
1022 {
1023         /* Remove conn's network callbacks.
1024          * NB I _have_ to restore the callback, rather than storing a noop,
1025          * since the socket could survive past this module being unloaded!! */
1026         sock->sk->sk_data_ready = conn->ksnc_saved_data_ready;
1027         sock->sk->sk_write_space = conn->ksnc_saved_write_space;
1028
1029         /* A callback could be in progress already; they hold a read lock
1030          * on ksnd_global_lock (to serialise with me) and NOOP if
1031          * sk_user_data is NULL. */
1032         sock->sk->sk_user_data = NULL;
1033
1034         return ;
1035 }
1036
1037 int
1038 ksocknal_lib_memory_pressure(ksock_conn_t *conn)
1039 {
1040         int            rc = 0;
1041         ksock_sched_t *sched;
1042
1043         sched = conn->ksnc_scheduler;
1044         spin_lock_bh(&sched->kss_lock);
1045
1046         if (!test_bit(SOCK_NOSPACE, &conn->ksnc_sock->flags) &&
1047             !conn->ksnc_tx_ready) {
1048                 /* SOCK_NOSPACE is set when the socket fills
1049                  * and cleared in the write_space callback
1050                  * (which also sets ksnc_tx_ready).  If
1051                  * SOCK_NOSPACE and ksnc_tx_ready are BOTH
1052                  * zero, I didn't fill the socket and
1053                  * write_space won't reschedule me, so I
1054                  * return -ENOMEM to get my caller to retry
1055                  * after a timeout */
1056                 rc = -ENOMEM;
1057         }
1058
1059         spin_unlock_bh(&sched->kss_lock);
1060
1061         return rc;
1062 }