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