The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/iscsi/icl_soft_proxy.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2012 The FreeBSD Foundation
    3  *
    4  * This software was developed by Edward Tomasz Napierala under sponsorship
    5  * from the FreeBSD Foundation.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  *
   28  */
   29 /*-
   30  * Copyright (c) 1982, 1986, 1989, 1990, 1993
   31  *      The Regents of the University of California.  All rights reserved.
   32  *
   33  * sendfile(2) and related extensions:
   34  * Copyright (c) 1998, David Greenman. All rights reserved.
   35  *
   36  * Redistribution and use in source and binary forms, with or without
   37  * modification, are permitted provided that the following conditions
   38  * are met:
   39  * 1. Redistributions of source code must retain the above copyright
   40  *    notice, this list of conditions and the following disclaimer.
   41  * 2. Redistributions in binary form must reproduce the above copyright
   42  *    notice, this list of conditions and the following disclaimer in the
   43  *    documentation and/or other materials provided with the distribution.
   44  * 3. Neither the name of the University nor the names of its contributors
   45  *    may be used to endorse or promote products derived from this software
   46  *    without specific prior written permission.
   47  *
   48  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   49  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   50  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   51  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   52  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   53  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   54  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   55  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   57  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   58  * SUCH DAMAGE.
   59  *
   60  *      @(#)uipc_syscalls.c     8.4 (Berkeley) 2/21/94
   61  */
   62 
   63 /*
   64  * iSCSI Common Layer, kernel proxy part.
   65  */
   66 
   67 #ifdef ICL_KERNEL_PROXY
   68 
   69 #include <sys/cdefs.h>
   70 __FBSDID("$FreeBSD$");
   71 
   72 #include <sys/param.h>
   73 #include <sys/capsicum.h>
   74 #include <sys/condvar.h>
   75 #include <sys/conf.h>
   76 #include <sys/lock.h>
   77 #include <sys/kernel.h>
   78 #include <sys/kthread.h>
   79 #include <sys/malloc.h>
   80 #include <sys/mutex.h>
   81 #include <sys/proc.h>
   82 #include <sys/socket.h>
   83 #include <sys/socketvar.h>
   84 #include <sys/sx.h>
   85 #include <sys/systm.h>
   86 #include <netinet/in.h>
   87 #include <netinet/tcp.h>
   88 
   89 #include <dev/iscsi/icl.h>
   90 
   91 struct icl_listen_sock {
   92         TAILQ_ENTRY(icl_listen_sock)    ils_next;
   93         struct icl_listen               *ils_listen;
   94         struct socket                   *ils_socket;
   95         bool                            ils_running;
   96         int                             ils_id;
   97 };
   98 
   99 struct icl_listen       {
  100         TAILQ_HEAD(, icl_listen_sock)   il_sockets;
  101         struct sx                       il_lock;
  102         void                            (*il_accept)(struct socket *,
  103                                             struct sockaddr *, int);
  104 };
  105 
  106 static MALLOC_DEFINE(M_ICL_PROXY, "ICL_PROXY", "iSCSI common layer proxy");
  107 
  108 int
  109 icl_soft_proxy_connect(struct icl_conn *ic, int domain, int socktype,
  110     int protocol, struct sockaddr *from_sa, struct sockaddr *to_sa)
  111 {
  112         struct socket *so;
  113         int error;
  114 
  115         error = socreate(domain, &so, socktype, protocol,
  116             curthread->td_ucred, curthread);
  117         if (error != 0)
  118                 return (error);
  119 
  120         if (from_sa != NULL) {
  121                 error = sobind(so, from_sa, curthread);
  122                 if (error != 0) {
  123                         soclose(so);
  124                         return (error);
  125                 }
  126         }
  127 
  128         error = soconnect(so, to_sa, curthread);
  129         if (error != 0) {
  130                 soclose(so);
  131                 return (error);
  132         }
  133 
  134         SOCK_LOCK(so);
  135         while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
  136                 error = msleep(&so->so_timeo, SOCK_MTX(so), PSOCK | PCATCH,
  137                     "icl_connect", 0);
  138                 if (error)
  139                         break;
  140         }
  141         if (error == 0) {
  142                 error = so->so_error;
  143                 so->so_error = 0;
  144         }
  145         SOCK_UNLOCK(so);
  146 
  147         if (error != 0) {
  148                 soclose(so);
  149                 return (error);
  150         }
  151 
  152         error = icl_soft_handoff_sock(ic, so);
  153         if (error != 0)
  154                 soclose(so);
  155 
  156         return (error);
  157 }
  158 
  159 struct icl_listen *
  160 icl_listen_new(void (*accept_cb)(struct socket *, struct sockaddr *, int))
  161 {
  162         struct icl_listen *il;
  163 
  164         il = malloc(sizeof(*il), M_ICL_PROXY, M_ZERO | M_WAITOK);
  165         TAILQ_INIT(&il->il_sockets);
  166         sx_init(&il->il_lock, "icl_listen");
  167         il->il_accept = accept_cb;
  168 
  169         return (il);
  170 }
  171 
  172 void
  173 icl_listen_free(struct icl_listen *il)
  174 {
  175         struct icl_listen_sock *ils;
  176         sbintime_t sbt, pr;
  177 
  178         sx_xlock(&il->il_lock);
  179         while (!TAILQ_EMPTY(&il->il_sockets)) {
  180                 ils = TAILQ_FIRST(&il->il_sockets);
  181                 while (ils->ils_running) {
  182                         ICL_DEBUG("waiting for accept thread to terminate");
  183                         sx_xunlock(&il->il_lock);
  184                         SOLISTEN_LOCK(ils->ils_socket);
  185                         ils->ils_socket->so_error = ENOTCONN;
  186                         SOLISTEN_UNLOCK(ils->ils_socket);
  187                         wakeup(&ils->ils_socket->so_timeo);
  188                         sbt = mstosbt(995);
  189                         pr = mstosbt(10);
  190                         pause_sbt("icl_unlisten", sbt, pr, 0);
  191                         sx_xlock(&il->il_lock);
  192                 }
  193 
  194                 TAILQ_REMOVE(&il->il_sockets, ils, ils_next);
  195                 soclose(ils->ils_socket);
  196                 free(ils, M_ICL_PROXY);
  197         }
  198         sx_xunlock(&il->il_lock);
  199 
  200         free(il, M_ICL_PROXY);
  201 }
  202 
  203 /*
  204  * XXX: Doing accept in a separate thread in each socket might not be the
  205  * best way to do stuff, but it's pretty clean and debuggable - and you
  206  * probably won't have hundreds of listening sockets anyway.
  207  */
  208 static void
  209 icl_accept_thread(void *arg)
  210 {
  211         struct icl_listen_sock *ils;
  212         struct socket *head, *so;
  213         struct sockaddr *sa;
  214         int error;
  215 
  216         ils = arg;
  217         head = ils->ils_socket;
  218 
  219         ils->ils_running = true;
  220 
  221         for (;;) {
  222                 SOLISTEN_LOCK(head);
  223                 error = solisten_dequeue(head, &so, 0);
  224                 if (error == ENOTCONN) {
  225                         /*
  226                          * XXXGL: ENOTCONN is our mark from icl_listen_free().
  227                          * Neither socket code, nor msleep(9) may return it.
  228                          */
  229                         ICL_DEBUG("terminating");
  230                         ils->ils_running = false;
  231                         kthread_exit();
  232                         return;
  233                 }
  234                 if (error) {
  235                         ICL_WARN("solisten_dequeue error %d", error);
  236                         continue;
  237                 }
  238 
  239                 sa = NULL;
  240                 error = soaccept(so, &sa);
  241                 if (error != 0) {
  242                         ICL_WARN("soaccept error %d", error);
  243                         if (sa != NULL)
  244                                 free(sa, M_SONAME);
  245                         soclose(so);
  246                         continue;
  247                 }
  248 
  249                 (ils->ils_listen->il_accept)(so, sa, ils->ils_id);
  250         }
  251 }
  252 
  253 static int
  254 icl_listen_add_tcp(struct icl_listen *il, int domain, int socktype,
  255     int protocol, struct sockaddr *sa, int portal_id)
  256 {
  257         struct icl_listen_sock *ils;
  258         struct socket *so;
  259         struct sockopt sopt;
  260         int error, one = 1;
  261 
  262         error = socreate(domain, &so, socktype, protocol,
  263             curthread->td_ucred, curthread);
  264         if (error != 0) {
  265                 ICL_WARN("socreate failed with error %d", error);
  266                 return (error);
  267         }
  268 
  269         sopt.sopt_dir = SOPT_SET;
  270         sopt.sopt_level = SOL_SOCKET;
  271         sopt.sopt_name = SO_REUSEADDR;
  272         sopt.sopt_val = &one;
  273         sopt.sopt_valsize = sizeof(one);
  274         sopt.sopt_td = NULL;
  275         error = sosetopt(so, &sopt);
  276         if (error != 0) {
  277                 ICL_WARN("failed to set SO_REUSEADDR with error %d", error);
  278                 soclose(so);
  279                 return (error);
  280         }
  281 
  282         error = sobind(so, sa, curthread);
  283         if (error != 0) {
  284                 ICL_WARN("sobind failed with error %d", error);
  285                 soclose(so);
  286                 return (error);
  287         }
  288 
  289         error = solisten(so, -1, curthread);
  290         if (error != 0) {
  291                 ICL_WARN("solisten failed with error %d", error);
  292                 soclose(so);
  293                 return (error);
  294         }
  295 
  296         ils = malloc(sizeof(*ils), M_ICL_PROXY, M_ZERO | M_WAITOK);
  297         ils->ils_listen = il;
  298         ils->ils_socket = so;
  299         ils->ils_id = portal_id;
  300 
  301         error = kthread_add(icl_accept_thread, ils, NULL, NULL, 0, 0, "iclacc");
  302         if (error != 0) {
  303                 ICL_WARN("kthread_add failed with error %d", error);
  304                 soclose(so);
  305                 free(ils, M_ICL_PROXY);
  306 
  307                 return (error);
  308         }
  309 
  310         sx_xlock(&il->il_lock);
  311         TAILQ_INSERT_TAIL(&il->il_sockets, ils, ils_next);
  312         sx_xunlock(&il->il_lock);
  313 
  314         return (0);
  315 }
  316 
  317 int
  318 icl_listen_add(struct icl_listen *il, bool rdma, int domain, int socktype,
  319     int protocol, struct sockaddr *sa, int portal_id)
  320 {
  321 
  322         if (rdma) {
  323                 ICL_DEBUG("RDMA not supported");
  324                 return (EOPNOTSUPP);
  325         }
  326 
  327         return (icl_listen_add_tcp(il, domain, socktype, protocol, sa,
  328             portal_id));
  329 }
  330 
  331 int
  332 icl_listen_remove(struct icl_listen *il, struct sockaddr *sa)
  333 {
  334 
  335         /*
  336          * XXX
  337          */
  338 
  339         return (EOPNOTSUPP);
  340 }
  341 
  342 #endif /* ICL_KERNEL_PROXY */

Cache object: 43e17b3b9a1fae5f0e08784bf64ccc47


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.