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