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