Whamcloud - gitweb
* Landed portals:b_port_step as follows...
[fs/lustre-release.git] / lnet / klnds / socklnd / socklnd_lib-linux.c
1 #include "socknal.h"
2
3 #ifdef CONFIG_SYSCTL
4 #define SOCKNAL_SYSCTL  200
5
6 #define SOCKNAL_SYSCTL_TIMEOUT          1
7 #define SOCKNAL_SYSCTL_EAGER_ACK        2
8 #define SOCKNAL_SYSCTL_ZERO_COPY        3
9 #define SOCKNAL_SYSCTL_TYPED            4
10 #define SOCKNAL_SYSCTL_MIN_BULK         5
11 #define SOCKNAL_SYSCTL_BUFFER_SIZE      6
12 #define SOCKNAL_SYSCTL_NAGLE            7
13 #define SOCKNAL_SYSCTL_IRQ_AFFINITY     8
14 #define SOCKNAL_SYSCTL_KEEPALIVE_IDLE   9
15 #define SOCKNAL_SYSCTL_KEEPALIVE_COUNT 10
16 #define SOCKNAL_SYSCTL_KEEPALIVE_INTVL 11
17
18 static ctl_table ksocknal_ctl_table[] = {
19         {SOCKNAL_SYSCTL_TIMEOUT, "timeout",
20          &ksocknal_tunables.ksnd_io_timeout, sizeof (int),
21          0644, NULL, &proc_dointvec},
22         {SOCKNAL_SYSCTL_EAGER_ACK, "eager_ack",
23          &ksocknal_tunables.ksnd_eager_ack, sizeof (int),
24          0644, NULL, &proc_dointvec},
25 #if SOCKNAL_ZC
26         {SOCKNAL_SYSCTL_ZERO_COPY, "zero_copy",
27          &ksocknal_tunables.ksnd_zc_min_frag, sizeof (int),
28          0644, NULL, &proc_dointvec},
29 #endif
30         {SOCKNAL_SYSCTL_TYPED, "typed",
31          &ksocknal_tunables.ksnd_typed_conns, sizeof (int),
32          0644, NULL, &proc_dointvec},
33         {SOCKNAL_SYSCTL_MIN_BULK, "min_bulk",
34          &ksocknal_tunables.ksnd_min_bulk, sizeof (int),
35          0644, NULL, &proc_dointvec},
36         {SOCKNAL_SYSCTL_BUFFER_SIZE, "buffer_size",
37          &ksocknal_tunables.ksnd_buffer_size, sizeof(int),
38          0644, NULL, &proc_dointvec},
39         {SOCKNAL_SYSCTL_NAGLE, "nagle",
40          &ksocknal_tunables.ksnd_nagle, sizeof(int),
41          0644, NULL, &proc_dointvec},
42 #if CPU_AFFINITY
43         {SOCKNAL_SYSCTL_IRQ_AFFINITY, "irq_affinity",
44          &ksocknal_tunables.ksnd_irq_affinity, sizeof(int),
45          0644, NULL, &proc_dointvec},
46 #endif
47         {SOCKNAL_SYSCTL_KEEPALIVE_IDLE, "keepalive_idle",
48          &ksocknal_tunables.ksnd_keepalive_idle, sizeof(int),
49          0644, NULL, &proc_dointvec},
50         {SOCKNAL_SYSCTL_KEEPALIVE_COUNT, "keepalive_count",
51          &ksocknal_tunables.ksnd_keepalive_count, sizeof(int),
52          0644, NULL, &proc_dointvec},
53         {SOCKNAL_SYSCTL_KEEPALIVE_INTVL, "keepalive_intvl",
54          &ksocknal_tunables.ksnd_keepalive_intvl, sizeof(int),
55          0644, NULL, &proc_dointvec},
56         { 0 }
57 };
58
59 ctl_table ksocknal_top_ctl_table[] = {
60         {SOCKNAL_SYSCTL, "socknal", NULL, 0, 0555, ksocknal_ctl_table},
61         { 0 }
62 };
63 #endif
64
65 void
66 ksocknal_lib_bind_irq (unsigned int irq)
67 {
68 #if (defined(CONFIG_SMP) && CPU_AFFINITY)
69         int              bind;
70         int              cpu;
71         unsigned long    flags;
72         char             cmdline[64];
73         ksock_irqinfo_t *info;
74         char            *argv[] = {"/bin/sh",
75                                    "-c",
76                                    cmdline,
77                                    NULL};
78         char            *envp[] = {"HOME=/",
79                                    "PATH=/sbin:/bin:/usr/sbin:/usr/bin",
80                                    NULL};
81
82         LASSERT (irq < NR_IRQS);
83         if (irq == 0)              /* software NIC or affinity disabled */
84                 return;
85
86         info = &ksocknal_data.ksnd_irqinfo[irq];
87
88         write_lock_irqsave (&ksocknal_data.ksnd_global_lock, flags);
89
90         LASSERT (info->ksni_valid);
91         bind = !info->ksni_bound;
92         info->ksni_bound = 1;
93
94         write_unlock_irqrestore (&ksocknal_data.ksnd_global_lock, flags);
95
96         if (!bind)                              /* bound already */
97                 return;
98
99         cpu = ksocknal_irqsched2cpu(info->ksni_sched);
100         snprintf (cmdline, sizeof (cmdline),
101                   "echo %d > /proc/irq/%u/smp_affinity", 1 << cpu, irq);
102
103         printk (KERN_INFO "Lustre: Binding irq %u to CPU %d with cmd: %s\n",
104                 irq, cpu, cmdline);
105
106         /* FIXME: Find a better method of setting IRQ affinity...
107          */
108
109         USERMODEHELPER(argv[0], argv, envp);
110 #endif
111 }
112
113 int
114 ksocknal_lib_get_conn_addrs (ksock_conn_t *conn)
115 {
116         struct sockaddr_in sin;
117         int                len = sizeof (sin);
118         int                rc;
119
120         rc = conn->ksnc_sock->ops->getname (conn->ksnc_sock,
121                                             (struct sockaddr *)&sin, &len, 2);
122         /* Didn't need the {get,put}connsock dance to deref ksnc_sock... */
123         LASSERT (!conn->ksnc_closing);
124
125         if (rc != 0) {
126                 CERROR ("Error %d getting sock peer IP\n", rc);
127                 return rc;
128         }
129
130         conn->ksnc_ipaddr = ntohl (sin.sin_addr.s_addr);
131         conn->ksnc_port   = ntohs (sin.sin_port);
132
133         rc = conn->ksnc_sock->ops->getname (conn->ksnc_sock,
134                                             (struct sockaddr *)&sin, &len, 0);
135         if (rc != 0) {
136                 CERROR ("Error %d getting sock local IP\n", rc);
137                 return rc;
138         }
139
140         conn->ksnc_myipaddr = ntohl (sin.sin_addr.s_addr);
141
142         return 0;
143 }
144
145 unsigned int
146 ksocknal_lib_sock_irq (struct socket *sock)
147 {
148         int                irq = 0;
149         struct dst_entry  *dst;
150
151         if (!ksocknal_tunables.ksnd_irq_affinity)
152                 return 0;
153
154         dst = sk_dst_get (sock->sk);
155         if (dst != NULL) {
156                 if (dst->dev != NULL) {
157                         irq = dst->dev->irq;
158                         if (irq >= NR_IRQS) {
159                                 CERROR ("Unexpected IRQ %x\n", irq);
160                                 irq = 0;
161                         }
162                 }
163                 dst_release (dst);
164         }
165
166         return (irq);
167 }
168
169 #if (SOCKNAL_ZC && SOCKNAL_VADDR_ZC)
170 static struct page *
171 ksocknal_kvaddr_to_page (unsigned long vaddr)
172 {
173         struct page *page;
174
175         if (vaddr >= VMALLOC_START &&
176             vaddr < VMALLOC_END)
177                 page = vmalloc_to_page ((void *)vaddr);
178 #if CONFIG_HIGHMEM
179         else if (vaddr >= PKMAP_BASE &&
180                  vaddr < (PKMAP_BASE + LAST_PKMAP * PAGE_SIZE))
181                 page = vmalloc_to_page ((void *)vaddr);
182                 /* in 2.4 ^ just walks the page tables */
183 #endif
184         else
185                 page = virt_to_page (vaddr);
186
187         if (page == NULL ||
188             !VALID_PAGE (page))
189                 return (NULL);
190
191         return (page);
192 }
193 #endif
194
195 int
196 ksocknal_lib_send_iov (ksock_conn_t *conn, ksock_tx_t *tx)
197 {
198         struct socket *sock = conn->ksnc_sock;
199 #if (SOCKNAL_ZC && SOCKNAL_VADDR_ZC)
200         unsigned long  vaddr = (unsigned long)iov->iov_base
201         int            offset = vaddr & (PAGE_SIZE - 1);
202         int            zcsize = MIN (iov->iov_len, PAGE_SIZE - offset);
203         struct page   *page;
204 #endif
205         int            nob;
206         int            rc;
207
208         /* NB we can't trust socket ops to either consume our iovs
209          * or leave them alone. */
210
211 #if (SOCKNAL_ZC && SOCKNAL_VADDR_ZC)
212         if (zcsize >= ksocknal_data.ksnd_zc_min_frag &&
213             (sock->sk->route_caps & NETIF_F_SG) &&
214             (sock->sk->route_caps & (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM | NETIF_F_HW_CSUM)) &&
215             (page = ksocknal_kvaddr_to_page (vaddr)) != NULL) {
216                 int msgflg = MSG_DONTWAIT;
217
218                 CDEBUG(D_NET, "vaddr %p, page %p->%p + offset %x for %d\n",
219                        (void *)vaddr, page, page_address(page), offset, zcsize);
220
221                 if (!list_empty (&conn->ksnc_tx_queue) ||
222                     zcsize < tx->tx_resid)
223                         msgflg |= MSG_MORE;
224
225                 rc = tcp_sendpage_zccd(sock, page, offset, zcsize, msgflg, &tx->tx_zccd);
226         } else
227 #endif
228         {
229 #if SOCKNAL_SINGLE_FRAG_TX
230                 struct iovec    scratch;
231                 struct iovec   *scratchiov = &scratch;
232                 int             niov = 1;
233 #else
234                 struct iovec   *scratchiov = conn->ksnc_tx_scratch_iov;
235                 int             niov = tx->tx_niov;
236 #endif
237                 struct msghdr msg = {
238                         .msg_name       = NULL,
239                         .msg_namelen    = 0,
240                         .msg_iov        = scratchiov,
241                         .msg_iovlen     = niov,
242                         .msg_control    = NULL,
243                         .msg_controllen = 0,
244                         .msg_flags      = MSG_DONTWAIT
245                 };
246                 mm_segment_t oldmm = get_fs();
247                 int  i;
248
249                 for (nob = i = 0; i < niov; i++) {
250                         scratchiov[i] = tx->tx_iov[i];
251                         nob += scratchiov[i].iov_len;
252                 }
253
254                 if (!list_empty(&conn->ksnc_tx_queue) ||
255                     nob < tx->tx_resid)
256                         msg.msg_flags |= MSG_MORE;
257
258                 set_fs (KERNEL_DS);
259                 rc = sock_sendmsg(sock, &msg, nob);
260                 set_fs (oldmm);
261         }
262         return rc;
263 }
264
265 int
266 ksocknal_lib_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx)
267 {
268         struct socket *sock = conn->ksnc_sock;
269         ptl_kiov_t    *kiov = tx->tx_kiov;
270         int            rc;
271         int            nob;
272
273         /* NB we can't trust socket ops to either consume our iovs
274          * or leave them alone. */
275
276 #if SOCKNAL_ZC
277         if (kiov->kiov_len >= ksocknal_tunables.ksnd_zc_min_frag &&
278             (sock->sk->route_caps & NETIF_F_SG) &&
279             (sock->sk->route_caps & (NETIF_F_IP_CSUM | NETIF_F_NO_CSUM | NETIF_F_HW_CSUM))) {
280                 struct page   *page = kiov->kiov_page;
281                 int            offset = kiov->kiov_offset;
282                 int            fragsize = kiov->kiov_len;
283                 int            msgflg = MSG_DONTWAIT;
284
285                 CDEBUG(D_NET, "page %p + offset %x for %d\n",
286                                page, offset, kiov->kiov_len);
287
288                 if (!list_empty(&conn->ksnc_tx_queue) ||
289                     fragsize < tx->tx_resid)
290                         msgflg |= MSG_MORE;
291
292                 rc = tcp_sendpage_zccd(sock, page, offset, fragsize, msgflg,
293                                        &tx->tx_zccd);
294         } else
295 #endif
296         {
297 #if SOCKNAL_SINGLE_FRAG_TX || !SOCKNAL_RISK_KMAP_DEADLOCK
298                 struct iovec  scratch;
299                 struct iovec *scratchiov = &scratch;
300                 int           niov = 1;
301 #else
302 #ifdef CONFIG_HIGHMEM
303 #warning "XXX risk of kmap deadlock on multiple frags..."
304 #endif
305                 struct iovec *scratchiov = conn->ksnc_tx_scratch_iov;
306                 int           niov = tx->tx_nkiov;
307 #endif
308                 struct msghdr msg = {
309                         .msg_name       = NULL,
310                         .msg_namelen    = 0,
311                         .msg_iov        = scratchiov,
312                         .msg_iovlen     = niov,
313                         .msg_control    = NULL,
314                         .msg_controllen = 0,
315                         .msg_flags      = MSG_DONTWAIT
316                 };
317                 mm_segment_t  oldmm = get_fs();
318                 int           i;
319
320                 for (nob = i = 0; i < niov; i++) {
321                         scratchiov[i].iov_base = kmap(kiov[i].kiov_page) +
322                                                  kiov[i].kiov_offset;
323                         nob += scratchiov[i].iov_len = kiov[i].kiov_len;
324                 }
325
326                 if (!list_empty(&conn->ksnc_tx_queue) ||
327                     nob < tx->tx_resid)
328                         msg.msg_flags |= MSG_DONTWAIT;
329
330                 set_fs (KERNEL_DS);
331                 rc = sock_sendmsg(sock, &msg, nob);
332                 set_fs (oldmm);
333
334                 for (i = 0; i < niov; i++)
335                         kunmap(kiov[i].kiov_page);
336         }
337         return rc;
338 }
339
340 void
341 ksocknal_lib_eager_ack (ksock_conn_t *conn)
342 {
343         int            opt = 1;
344         mm_segment_t   oldmm = get_fs();
345         struct socket *sock = conn->ksnc_sock;
346
347         /* Remind the socket to ACK eagerly.  If I don't, the socket might
348          * think I'm about to send something it could piggy-back the ACK
349          * on, introducing delay in completing zero-copy sends in my
350          * peer. */
351
352         set_fs(KERNEL_DS);
353         sock->ops->setsockopt (sock, SOL_TCP, TCP_QUICKACK,
354                                (char *)&opt, sizeof (opt));
355         set_fs(oldmm);
356 }
357
358 int
359 ksocknal_lib_recv_iov (ksock_conn_t *conn)
360 {
361 #if SOCKNAL_SINGLE_FRAG_RX
362         struct iovec  scratch;
363         struct iovec *scratchiov = &scratch;
364         int           niov = 1;
365 #else
366         struct iovec *scratchiov = conn->ksnc_rx_scratch_iov;
367         int           niov = conn->ksnc_rx_niov;
368 #endif
369         struct iovec *iov = conn->ksnc_rx_iov;
370         struct msghdr msg = {
371                 .msg_name       = NULL,
372                 .msg_namelen    = 0,
373                 .msg_iov        = scratchiov,
374                 .msg_iovlen     = niov,
375                 .msg_control    = NULL,
376                 .msg_controllen = 0,
377                 .msg_flags      = 0
378         };
379         mm_segment_t oldmm = get_fs();
380         int          nob;
381         int          i;
382         int          rc;
383
384         /* NB we can't trust socket ops to either consume our iovs
385          * or leave them alone. */
386         LASSERT (niov > 0);
387
388         for (nob = i = 0; i < niov; i++) {
389                 scratchiov[i] = iov[i];
390                 nob += scratchiov[i].iov_len;
391         }
392         LASSERT (nob <= conn->ksnc_rx_nob_wanted);
393
394         set_fs (KERNEL_DS);
395         rc = sock_recvmsg (conn->ksnc_sock, &msg, nob, MSG_DONTWAIT);
396         /* NB this is just a boolean..........................^ */
397         set_fs (oldmm);
398
399         return rc;
400 }
401
402 int
403 ksocknal_lib_recv_kiov (ksock_conn_t *conn)
404 {
405 #if SOCKNAL_SINGLE_FRAG_RX || !SOCKNAL_RISK_KMAP_DEADLOCK
406         struct iovec  scratch;
407         struct iovec *scratchiov = &scratch;
408         int           niov = 1;
409 #else
410 #ifdef CONFIG_HIGHMEM
411 #warning "XXX risk of kmap deadlock on multiple frags..."
412 #endif
413         struct iovec *scratchiov = conn->ksnc_rx_scratch_iov;
414         int           niov = conn->ksnc_rx_nkiov;
415 #endif
416         ptl_kiov_t   *kiov = conn->ksnc_rx_kiov;
417         struct msghdr msg = {
418                 .msg_name       = NULL,
419                 .msg_namelen    = 0,
420                 .msg_iov        = scratchiov,
421                 .msg_iovlen     = niov,
422                 .msg_control    = NULL,
423                 .msg_controllen = 0,
424                 .msg_flags      = 0
425         };
426         mm_segment_t oldmm = get_fs();
427         int          nob;
428         int          i;
429         int          rc;
430
431         /* NB we can't trust socket ops to either consume our iovs
432          * or leave them alone. */
433         for (nob = i = 0; i < niov; i++) {
434                 scratchiov[i].iov_base = kmap(kiov[i].kiov_page) + kiov[i].kiov_offset;
435                 nob += scratchiov[i].iov_len = kiov[i].kiov_len;
436         }
437         LASSERT (nob <= conn->ksnc_rx_nob_wanted);
438
439         set_fs (KERNEL_DS);
440         rc = sock_recvmsg (conn->ksnc_sock, &msg, nob, MSG_DONTWAIT);
441         /* NB this is just a boolean.......................^ */
442         set_fs (oldmm);
443
444         for (i = 0; i < niov; i++)
445                 kunmap(kiov[i].kiov_page);
446
447         return (rc);
448 }
449
450 int
451 ksocknal_lib_sock_write (struct socket *sock, void *buffer, int nob)
452 {
453         int           rc;
454         mm_segment_t  oldmm = get_fs();
455
456         while (nob > 0) {
457                 struct iovec  iov = {
458                         .iov_base = buffer,
459                         .iov_len  = nob
460                 };
461                 struct msghdr msg = {
462                         .msg_name       = NULL,
463                         .msg_namelen    = 0,
464                         .msg_iov        = &iov,
465                         .msg_iovlen     = 1,
466                         .msg_control    = NULL,
467                         .msg_controllen = 0,
468                         .msg_flags      = 0
469                 };
470
471                 set_fs (KERNEL_DS);
472                 rc = sock_sendmsg (sock, &msg, iov.iov_len);
473                 set_fs (oldmm);
474
475                 if (rc < 0)
476                         return (rc);
477
478                 if (rc == 0) {
479                         CERROR ("Unexpected zero rc\n");
480                         return (-ECONNABORTED);
481                 }
482
483                 buffer = ((char *)buffer) + rc;
484                 nob -= rc;
485         }
486
487         return (0);
488 }
489
490 int
491 ksocknal_lib_sock_read (struct socket *sock, void *buffer, int nob)
492 {
493         int           rc;
494         mm_segment_t  oldmm = get_fs();
495
496         while (nob > 0) {
497                 struct iovec  iov = {
498                         .iov_base = buffer,
499                         .iov_len  = nob
500                 };
501                 struct msghdr msg = {
502                         .msg_name       = NULL,
503                         .msg_namelen    = 0,
504                         .msg_iov        = &iov,
505                         .msg_iovlen     = 1,
506                         .msg_control    = NULL,
507                         .msg_controllen = 0,
508                         .msg_flags      = 0
509                 };
510
511                 set_fs (KERNEL_DS);
512                 rc = sock_recvmsg (sock, &msg, iov.iov_len, 0);
513                 set_fs (oldmm);
514
515                 if (rc < 0)
516                         return (rc);
517
518                 if (rc == 0)
519                         return (-ECONNABORTED);
520
521                 buffer = ((char *)buffer) + rc;
522                 nob -= rc;
523         }
524
525         return (0);
526 }
527
528 int
529 ksocknal_lib_get_conn_tunables (ksock_conn_t *conn, int *txmem, int *rxmem, int *nagle)
530 {
531         mm_segment_t   oldmm = get_fs ();
532         struct socket *sock = conn->ksnc_sock;
533         int            len;
534         int            rc;
535
536         rc = ksocknal_getconnsock (conn);
537         if (rc != 0) {
538                 LASSERT (conn->ksnc_closing);
539                 *txmem = *rxmem = *nagle = 0;
540                 return (-ESHUTDOWN);
541         }
542
543         set_fs (KERNEL_DS);
544
545         len = sizeof(*txmem);
546         rc = sock_getsockopt(sock, SOL_SOCKET, SO_SNDBUF,
547                              (char *)txmem, &len);
548         if (rc == 0) {
549                 len = sizeof(*rxmem);
550                 rc = sock_getsockopt(sock, SOL_SOCKET, SO_RCVBUF,
551                                      (char *)rxmem, &len);
552         }
553         if (rc == 0) {
554                 len = sizeof(*nagle);
555                 rc = sock->ops->getsockopt(sock, SOL_TCP, TCP_NODELAY,
556                                            (char *)nagle, &len);
557         }
558
559         set_fs (oldmm);
560         ksocknal_putconnsock (conn);
561
562         if (rc == 0)
563                 *nagle = !*nagle;
564         else
565                 *txmem = *rxmem = *nagle = 0;
566
567         return (rc);
568 }
569
570 int
571 ksocknal_lib_setup_sock (struct socket *sock)
572 {
573         mm_segment_t    oldmm = get_fs ();
574         int             rc;
575         int             option;
576         int             keep_idle;
577         int             keep_intvl;
578         int             keep_count;
579         int             do_keepalive;
580         struct linger   linger;
581
582         sock->sk->sk_allocation = GFP_NOFS;
583
584         /* Ensure this socket aborts active sends immediately when we close
585          * it. */
586
587         linger.l_onoff = 0;
588         linger.l_linger = 0;
589
590         set_fs (KERNEL_DS);
591         rc = sock_setsockopt (sock, SOL_SOCKET, SO_LINGER,
592                               (char *)&linger, sizeof (linger));
593         set_fs (oldmm);
594         if (rc != 0) {
595                 CERROR ("Can't set SO_LINGER: %d\n", rc);
596                 return (rc);
597         }
598
599         option = -1;
600         set_fs (KERNEL_DS);
601         rc = sock->ops->setsockopt (sock, SOL_TCP, TCP_LINGER2,
602                                     (char *)&option, sizeof (option));
603         set_fs (oldmm);
604         if (rc != 0) {
605                 CERROR ("Can't set SO_LINGER2: %d\n", rc);
606                 return (rc);
607         }
608
609         if (!ksocknal_tunables.ksnd_nagle) {
610                 option = 1;
611
612                 set_fs (KERNEL_DS);
613                 rc = sock->ops->setsockopt (sock, SOL_TCP, TCP_NODELAY,
614                                             (char *)&option, sizeof (option));
615                 set_fs (oldmm);
616                 if (rc != 0) {
617                         CERROR ("Can't disable nagle: %d\n", rc);
618                         return (rc);
619                 }
620         }
621
622         if (ksocknal_tunables.ksnd_buffer_size > 0) {
623                 option = ksocknal_tunables.ksnd_buffer_size;
624
625                 set_fs (KERNEL_DS);
626                 rc = sock_setsockopt (sock, SOL_SOCKET, SO_SNDBUF,
627                                       (char *)&option, sizeof (option));
628                 set_fs (oldmm);
629                 if (rc != 0) {
630                         CERROR ("Can't set send buffer %d: %d\n",
631                                 option, rc);
632                         return (rc);
633                 }
634
635                 set_fs (KERNEL_DS);
636                 rc = sock_setsockopt (sock, SOL_SOCKET, SO_RCVBUF,
637                                       (char *)&option, sizeof (option));
638                 set_fs (oldmm);
639                 if (rc != 0) {
640                         CERROR ("Can't set receive buffer %d: %d\n",
641                                 option, rc);
642                         return (rc);
643                 }
644         }
645
646         /* snapshot tunables */
647         keep_idle  = ksocknal_tunables.ksnd_keepalive_idle;
648         keep_count = ksocknal_tunables.ksnd_keepalive_count;
649         keep_intvl = ksocknal_tunables.ksnd_keepalive_intvl;
650
651         do_keepalive = (keep_idle > 0 && keep_count > 0 && keep_intvl > 0);
652
653         option = (do_keepalive ? 1 : 0);
654         set_fs (KERNEL_DS);
655         rc = sock_setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE,
656                               (char *)&option, sizeof (option));
657         set_fs (oldmm);
658         if (rc != 0) {
659                 CERROR ("Can't set SO_KEEPALIVE: %d\n", rc);
660                 return (rc);
661         }
662
663         if (!do_keepalive)
664                 return (0);
665
666         set_fs (KERNEL_DS);
667         rc = sock->ops->setsockopt (sock, SOL_TCP, TCP_KEEPIDLE,
668                                     (char *)&keep_idle, sizeof (keep_idle));
669         set_fs (oldmm);
670         if (rc != 0) {
671                 CERROR ("Can't set TCP_KEEPIDLE: %d\n", rc);
672                 return (rc);
673         }
674
675         set_fs (KERNEL_DS);
676         rc = sock->ops->setsockopt (sock, SOL_TCP, TCP_KEEPINTVL,
677                                     (char *)&keep_intvl, sizeof (keep_intvl));
678         set_fs (oldmm);
679         if (rc != 0) {
680                 CERROR ("Can't set TCP_KEEPINTVL: %d\n", rc);
681                 return (rc);
682         }
683
684         set_fs (KERNEL_DS);
685         rc = sock->ops->setsockopt (sock, SOL_TCP, TCP_KEEPCNT,
686                                     (char *)&keep_count, sizeof (keep_count));
687         set_fs (oldmm);
688         if (rc != 0) {
689                 CERROR ("Can't set TCP_KEEPCNT: %d\n", rc);
690                 return (rc);
691         }
692
693         return (0);
694 }
695
696 int
697 ksocknal_lib_connect_sock(struct socket **sockp, int *may_retry,
698                       ksock_route_t *route, int local_port)
699 {
700         struct sockaddr_in  locaddr;
701         struct sockaddr_in  srvaddr;
702         struct socket      *sock;
703         int                 rc;
704         int                 option;
705         mm_segment_t        oldmm = get_fs();
706         struct timeval      tv;
707
708         memset(&locaddr, 0, sizeof(locaddr));
709         locaddr.sin_family = AF_INET;
710         locaddr.sin_port = htons(local_port);
711         locaddr.sin_addr.s_addr =
712                 (route->ksnr_myipaddr != 0) ? htonl(route->ksnr_myipaddr)
713                                             : INADDR_ANY;
714
715         memset (&srvaddr, 0, sizeof (srvaddr));
716         srvaddr.sin_family = AF_INET;
717         srvaddr.sin_port = htons (route->ksnr_port);
718         srvaddr.sin_addr.s_addr = htonl (route->ksnr_ipaddr);
719
720         *may_retry = 0;
721
722         rc = sock_create (PF_INET, SOCK_STREAM, 0, &sock);
723         *sockp = sock;
724         if (rc != 0) {
725                 CERROR ("Can't create autoconnect socket: %d\n", rc);
726                 return (rc);
727         }
728
729         /* Ugh; have to map_fd for compatibility with sockets passed in
730          * from userspace.  And we actually need the sock->file refcounting
731          * that this gives you :) */
732
733         rc = sock_map_fd (sock);
734         if (rc < 0) {
735                 sock_release (sock);
736                 CERROR ("sock_map_fd error %d\n", rc);
737                 return (rc);
738         }
739
740         /* NB the file descriptor (rc) now owns the ref on sock->file */
741         LASSERT (sock->file != NULL);
742         LASSERT (file_count(sock->file) == 1);
743
744         get_file(sock->file);                /* extra ref makes sock->file */
745         sys_close(rc);                       /* survive this close */
746
747         /* Still got a single ref on sock->file */
748         LASSERT (file_count(sock->file) == 1);
749
750         /* Set the socket timeouts, so our connection attempt completes in
751          * finite time */
752         tv.tv_sec = ksocknal_tunables.ksnd_io_timeout;
753         tv.tv_usec = 0;
754
755         set_fs (KERNEL_DS);
756         rc = sock_setsockopt (sock, SOL_SOCKET, SO_SNDTIMEO,
757                               (char *)&tv, sizeof (tv));
758         set_fs (oldmm);
759         if (rc != 0) {
760                 CERROR ("Can't set send timeout %d: %d\n",
761                         ksocknal_tunables.ksnd_io_timeout, rc);
762                 goto failed;
763         }
764
765         set_fs (KERNEL_DS);
766         rc = sock_setsockopt (sock, SOL_SOCKET, SO_RCVTIMEO,
767                               (char *)&tv, sizeof (tv));
768         set_fs (oldmm);
769         if (rc != 0) {
770                 CERROR ("Can't set receive timeout %d: %d\n",
771                         ksocknal_tunables.ksnd_io_timeout, rc);
772                 goto failed;
773         }
774
775         set_fs (KERNEL_DS);
776         option = 1;
777         rc = sock_setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
778                              (char *)&option, sizeof (option));
779         set_fs (oldmm);
780         if (rc != 0) {
781                 CERROR("Can't set SO_REUSEADDR for socket: %d\n", rc);
782                 goto failed;
783         }
784
785         rc = sock->ops->bind(sock,
786                              (struct sockaddr *)&locaddr, sizeof(locaddr));
787         if (rc == -EADDRINUSE) {
788                 CDEBUG(D_NET, "Port %d already in use\n", local_port);
789                 *may_retry = 1;
790                 goto failed;
791         }
792         if (rc != 0) {
793                 CERROR("Error trying to bind to reserved port %d: %d\n",
794                        local_port, rc);
795                 goto failed;
796         }
797
798         rc = sock->ops->connect(sock,
799                                 (struct sockaddr *)&srvaddr, sizeof(srvaddr),
800                                 sock->file->f_flags);
801         if (rc == 0)
802                 return 0;
803
804         /* EADDRNOTAVAIL probably means we're already connected to the same
805          * peer/port on the same local port on a differently typed
806          * connection.  Let our caller retry with a different local
807          * port... */
808         *may_retry = (rc == -EADDRNOTAVAIL);
809
810         CDEBUG(*may_retry ? D_NET : D_ERROR,
811                "Error %d connecting %u.%u.%u.%u/%d -> %u.%u.%u.%u/%d\n", rc,
812                HIPQUAD(route->ksnr_myipaddr), local_port,
813                HIPQUAD(route->ksnr_ipaddr), route->ksnr_port);
814
815  failed:
816         fput(sock->file);
817         return rc;
818 }
819
820 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
821 struct tcp_opt *sock2tcp_opt(struct sock *sk)
822 {
823         return &(sk->tp_pinfo.af_tcp);
824 }
825 #else
826 struct tcp_opt *sock2tcp_opt(struct sock *sk)
827 {
828         struct tcp_sock *s = (struct tcp_sock *)sk;
829         return &s->tcp;
830 }
831 #endif
832
833 void
834 ksocknal_lib_push_conn (ksock_conn_t *conn)
835 {
836         struct sock    *sk;
837         struct tcp_opt *tp;
838         int             nonagle;
839         int             val = 1;
840         int             rc;
841         mm_segment_t    oldmm;
842
843         rc = ksocknal_getconnsock (conn);
844         if (rc != 0)                            /* being shut down */
845                 return;
846
847         sk = conn->ksnc_sock->sk;
848         tp = sock2tcp_opt(sk);
849
850         lock_sock (sk);
851         nonagle = tp->nonagle;
852         tp->nonagle = 1;
853         release_sock (sk);
854
855         oldmm = get_fs ();
856         set_fs (KERNEL_DS);
857
858         rc = sk->sk_prot->setsockopt (sk, SOL_TCP, TCP_NODELAY,
859                                       (char *)&val, sizeof (val));
860         LASSERT (rc == 0);
861
862         set_fs (oldmm);
863
864         lock_sock (sk);
865         tp->nonagle = nonagle;
866         release_sock (sk);
867
868         ksocknal_putconnsock (conn);
869 }
870
871 extern void ksocknal_read_callback (ksock_conn_t *conn);
872 extern void ksocknal_write_callback (ksock_conn_t *conn);
873 /*
874  * socket call back in Linux
875  */
876 static void
877 ksocknal_data_ready (struct sock *sk, int n)
878 {
879         ksock_conn_t  *conn;
880         ENTRY;
881
882         /* interleave correctly with closing sockets... */
883         read_lock (&ksocknal_data.ksnd_global_lock);
884
885         conn = sk->sk_user_data;
886         if (conn == NULL) {             /* raced with ksocknal_terminate_conn */
887                 LASSERT (sk->sk_data_ready != &ksocknal_data_ready);
888                 sk->sk_data_ready (sk, n);
889         } else
890                 ksocknal_read_callback(conn);
891
892         read_unlock (&ksocknal_data.ksnd_global_lock);
893
894         EXIT;
895 }
896
897 static void
898 ksocknal_write_space (struct sock *sk)
899 {
900         ksock_conn_t  *conn;
901
902         /* interleave correctly with closing sockets... */
903         read_lock (&ksocknal_data.ksnd_global_lock);
904
905         conn = sk->sk_user_data;
906
907         CDEBUG(D_NET, "sk %p wspace %d low water %d conn %p%s%s%s\n",
908                sk, tcp_wspace(sk), SOCKNAL_TX_LOW_WATER(sk), conn,
909                (conn == NULL) ? "" : (conn->ksnc_tx_ready ?
910                                       " ready" : " blocked"),
911                (conn == NULL) ? "" : (conn->ksnc_tx_scheduled ?
912                                       " scheduled" : " idle"),
913                (conn == NULL) ? "" : (list_empty (&conn->ksnc_tx_queue) ?
914                                       " empty" : " queued"));
915
916         if (conn == NULL) {             /* raced with ksocknal_terminate_conn */
917                 LASSERT (sk->sk_write_space != &ksocknal_write_space);
918                 sk->sk_write_space (sk);
919
920                 read_unlock (&ksocknal_data.ksnd_global_lock);
921                 return;
922         }
923
924         if (tcp_wspace(sk) >= SOCKNAL_TX_LOW_WATER(sk)) { /* got enough space */
925                 ksocknal_write_callback(conn);
926
927                 /* Clear SOCK_NOSPACE _after_ ksocknal_write_callback so the
928                  * ENOMEM check in ksocknal_transmit is race-free (think about
929                  * it). */
930
931                 clear_bit (SOCK_NOSPACE, &sk->sk_socket->flags);
932         }
933
934         read_unlock (&ksocknal_data.ksnd_global_lock);
935 }
936
937 void
938 ksocknal_lib_save_callback(struct socket *sock, ksock_conn_t *conn)
939 {
940         conn->ksnc_saved_data_ready = sock->sk->sk_data_ready;
941         conn->ksnc_saved_write_space = sock->sk->sk_write_space;
942 }
943
944 void
945 ksocknal_lib_set_callback(struct socket *sock,  ksock_conn_t *conn)
946 {
947         sock->sk->sk_user_data = conn;
948         sock->sk->sk_data_ready = ksocknal_data_ready;
949         sock->sk->sk_write_space = ksocknal_write_space;
950         return;
951 }
952
953 void
954 ksocknal_lib_act_callback(struct socket *sock, ksock_conn_t *conn)
955 {
956         ksocknal_data_ready (sock->sk, 0);
957         ksocknal_write_space (sock->sk);
958         return;
959 }
960
961 void
962 ksocknal_lib_reset_callback(struct socket *sock, ksock_conn_t *conn)
963 {
964         /* Remove conn's network callbacks.
965          * NB I _have_ to restore the callback, rather than storing a noop,
966          * since the socket could survive past this module being unloaded!! */
967         sock->sk->sk_data_ready = conn->ksnc_saved_data_ready;
968         sock->sk->sk_write_space = conn->ksnc_saved_write_space;
969
970         /* A callback could be in progress already; they hold a read lock
971          * on ksnd_global_lock (to serialise with me) and NOOP if
972          * sk_user_data is NULL. */
973         sock->sk->sk_user_data = NULL;
974
975         return ;
976 }
977