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/netsmb/smb_iod.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) 2000-2001 Boris Popov
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *    This product includes software developed by Boris Popov.
   16  * 4. Neither the name of the author nor the names of any co-contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __FBSDID("$FreeBSD$");
   35  
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/endian.h>
   39 #include <sys/proc.h>
   40 #include <sys/kernel.h>
   41 #include <sys/kthread.h>
   42 #include <sys/malloc.h>
   43 #include <sys/mbuf.h>
   44 #include <sys/unistd.h>
   45 
   46 #include <netsmb/smb.h>
   47 #include <netsmb/smb_conn.h>
   48 #include <netsmb/smb_rq.h>
   49 #include <netsmb/smb_tran.h>
   50 #include <netsmb/smb_trantcp.h>
   51 
   52 
   53 #define SMBIOD_SLEEP_TIMO       2
   54 #define SMBIOD_PING_TIMO        60      /* seconds */
   55 
   56 #define SMB_IOD_EVLOCKPTR(iod)  (&((iod)->iod_evlock))
   57 #define SMB_IOD_EVLOCK(iod)     smb_sl_lock(&((iod)->iod_evlock))
   58 #define SMB_IOD_EVUNLOCK(iod)   smb_sl_unlock(&((iod)->iod_evlock))
   59 
   60 #define SMB_IOD_RQLOCKPTR(iod)  (&((iod)->iod_rqlock))
   61 #define SMB_IOD_RQLOCK(iod)     smb_sl_lock(&((iod)->iod_rqlock))
   62 #define SMB_IOD_RQUNLOCK(iod)   smb_sl_unlock(&((iod)->iod_rqlock))
   63 
   64 #define smb_iod_wakeup(iod)     wakeup(&(iod)->iod_flags)
   65 
   66 
   67 static MALLOC_DEFINE(M_SMBIOD, "SMBIOD", "SMB network io daemon");
   68 
   69 static int smb_iod_next;
   70 
   71 static int  smb_iod_sendall(struct smbiod *iod);
   72 static int  smb_iod_disconnect(struct smbiod *iod);
   73 static void smb_iod_thread(void *);
   74 
   75 static __inline void
   76 smb_iod_rqprocessed(struct smb_rq *rqp, int error)
   77 {
   78         SMBRQ_SLOCK(rqp);
   79         rqp->sr_lerror = error;
   80         rqp->sr_rpgen++;
   81         rqp->sr_state = SMBRQ_NOTIFIED;
   82         wakeup(&rqp->sr_state);
   83         SMBRQ_SUNLOCK(rqp);
   84 }
   85 
   86 static void
   87 smb_iod_invrq(struct smbiod *iod)
   88 {
   89         struct smb_rq *rqp;
   90 
   91         /*
   92          * Invalidate all outstanding requests for this connection
   93          */
   94         SMB_IOD_RQLOCK(iod);
   95         TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
   96                 if (rqp->sr_flags & SMBR_INTERNAL)
   97                         SMBRQ_SUNLOCK(rqp);
   98                 rqp->sr_flags |= SMBR_RESTART;
   99                 smb_iod_rqprocessed(rqp, ENOTCONN);
  100         }
  101         SMB_IOD_RQUNLOCK(iod);
  102 }
  103 
  104 static void
  105 smb_iod_closetran(struct smbiod *iod)
  106 {
  107         struct smb_vc *vcp = iod->iod_vc;
  108         struct proc *p = iod->iod_p;
  109 
  110         if (vcp->vc_tdata == NULL)
  111                 return;
  112         SMB_TRAN_DISCONNECT(vcp, p);
  113         SMB_TRAN_DONE(vcp, p);
  114         vcp->vc_tdata = NULL;
  115 }
  116 
  117 static void
  118 smb_iod_dead(struct smbiod *iod)
  119 {
  120         iod->iod_state = SMBIOD_ST_DEAD;
  121         smb_iod_closetran(iod);
  122         smb_iod_invrq(iod);
  123 }
  124 
  125 static int
  126 smb_iod_connect(struct smbiod *iod)
  127 {
  128         struct smb_vc *vcp = iod->iod_vc;
  129         struct proc *p = iod->iod_p;
  130         int error;
  131 
  132         SMBIODEBUG("%d\n", iod->iod_state);
  133         switch(iod->iod_state) {
  134             case SMBIOD_ST_VCACTIVE:
  135                 SMBERROR("called for already opened connection\n");
  136                 return EISCONN;
  137             case SMBIOD_ST_DEAD:
  138                 return ENOTCONN;        /* XXX: last error code ? */
  139             default:
  140                 break;
  141         }
  142         vcp->vc_genid++;
  143         error = (int)SMB_TRAN_CREATE(vcp, p);
  144         if (error)
  145                 goto fail;
  146         SMBIODEBUG("tcreate\n");
  147         if (vcp->vc_laddr) {
  148                 error = (int)SMB_TRAN_BIND(vcp, vcp->vc_laddr, p);
  149                 if (error)
  150                         goto fail;
  151         }
  152         SMBIODEBUG("tbind\n");
  153         error = (int)SMB_TRAN_CONNECT(vcp, vcp->vc_paddr, p);
  154         if (error)
  155                 goto fail;
  156         SMB_TRAN_SETPARAM(vcp, SMBTP_SELECTID, &iod->iod_flags);
  157         iod->iod_state = SMBIOD_ST_TRANACTIVE;
  158         SMBIODEBUG("tconnect\n");
  159         /* vcp->vc_mid = 0;*/
  160         error = (int)smb_smb_negotiate(vcp, &iod->iod_scred);
  161         if (error)
  162                 goto fail;
  163         SMBIODEBUG("snegotiate\n");
  164         error = (int)smb_smb_ssnsetup(vcp, &iod->iod_scred);
  165         if (error)
  166                 goto fail;
  167         iod->iod_state = SMBIOD_ST_VCACTIVE;
  168         SMBIODEBUG("completed\n");
  169         smb_iod_invrq(iod);
  170         return (0);
  171 
  172  fail:
  173         smb_iod_dead(iod);
  174         return (error);
  175 }
  176 
  177 static int
  178 smb_iod_disconnect(struct smbiod *iod)
  179 {
  180         struct smb_vc *vcp = iod->iod_vc;
  181 
  182         SMBIODEBUG("\n");
  183         if (iod->iod_state == SMBIOD_ST_VCACTIVE) {
  184                 smb_smb_ssnclose(vcp, &iod->iod_scred);
  185                 iod->iod_state = SMBIOD_ST_TRANACTIVE;
  186         }
  187         vcp->vc_smbuid = SMB_UID_UNKNOWN;
  188         smb_iod_closetran(iod);
  189         iod->iod_state = SMBIOD_ST_NOTCONN;
  190         return 0;
  191 }
  192 
  193 static int
  194 smb_iod_treeconnect(struct smbiod *iod, struct smb_share *ssp)
  195 {
  196         int error;
  197 
  198         if (iod->iod_state != SMBIOD_ST_VCACTIVE) {
  199                 if (iod->iod_state != SMBIOD_ST_DEAD)
  200                         return ENOTCONN;
  201                 iod->iod_state = SMBIOD_ST_RECONNECT;
  202                 error = smb_iod_connect(iod);
  203                 if (error)
  204                         return error;
  205         }
  206         SMBIODEBUG("tree reconnect\n");
  207         SMBS_ST_LOCK(ssp);
  208         ssp->ss_flags |= SMBS_RECONNECTING;
  209         SMBS_ST_UNLOCK(ssp);
  210         error = smb_smb_treeconnect(ssp, &iod->iod_scred);
  211         SMBS_ST_LOCK(ssp);
  212         ssp->ss_flags &= ~SMBS_RECONNECTING;
  213         SMBS_ST_UNLOCK(ssp);
  214         wakeup(&ssp->ss_vcgenid);
  215         return error;
  216 }
  217 
  218 static int
  219 smb_iod_sendrq(struct smbiod *iod, struct smb_rq *rqp)
  220 {
  221         struct proc *p = iod->iod_p;
  222         struct smb_vc *vcp = iod->iod_vc;
  223         struct smb_share *ssp = rqp->sr_share;
  224         struct mbuf *m;
  225         int error;
  226 
  227         SMBIODEBUG("iod_state = %d\n", iod->iod_state);
  228         switch (iod->iod_state) {
  229             case SMBIOD_ST_NOTCONN:
  230                 smb_iod_rqprocessed(rqp, ENOTCONN);
  231                 return 0;
  232             case SMBIOD_ST_DEAD:
  233                 iod->iod_state = SMBIOD_ST_RECONNECT;
  234                 return 0;
  235             case SMBIOD_ST_RECONNECT:
  236                 return 0;
  237             default:
  238                 break;
  239         }
  240         if (rqp->sr_sendcnt == 0) {
  241 #ifdef movedtoanotherplace
  242                 if (vcp->vc_maxmux != 0 && iod->iod_muxcnt >= vcp->vc_maxmux)
  243                         return 0;
  244 #endif
  245                 *rqp->sr_rqtid = htole16(ssp ? ssp->ss_tid : SMB_TID_UNKNOWN);
  246                 *rqp->sr_rquid = htole16(vcp ? vcp->vc_smbuid : 0);
  247                 mb_fixhdr(&rqp->sr_rq);
  248                 if (vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE)
  249                         smb_rq_sign(rqp);
  250         }
  251         if (rqp->sr_sendcnt++ > 5) {
  252                 rqp->sr_flags |= SMBR_RESTART;
  253                 smb_iod_rqprocessed(rqp, rqp->sr_lerror);
  254                 /*
  255                  * If all attempts to send a request failed, then
  256                  * something is seriously hosed.
  257                  */
  258                 return ENOTCONN;
  259         }
  260         SMBSDEBUG("M:%04x, P:%04x, U:%04x, T:%04x\n", rqp->sr_mid, 0, 0, 0);
  261         m_dumpm(rqp->sr_rq.mb_top);
  262         m = m_copym(rqp->sr_rq.mb_top, 0, M_COPYALL, M_WAITOK);
  263         error = rqp->sr_lerror = m ? SMB_TRAN_SEND(vcp, m, p) : ENOBUFS;
  264         if (error == 0) {
  265                 getnanotime(&rqp->sr_timesent);
  266                 iod->iod_lastrqsent = rqp->sr_timesent;
  267                 rqp->sr_flags |= SMBR_SENT;
  268                 rqp->sr_state = SMBRQ_SENT;
  269                 return 0;
  270         }
  271         /*
  272          * Check for fatal errors
  273          */
  274         if (SMB_TRAN_FATAL(vcp, error)) {
  275                 /*
  276                  * No further attempts should be made
  277                  */
  278                 return ENOTCONN;
  279         }
  280         if (smb_rq_intr(rqp))
  281                 smb_iod_rqprocessed(rqp, EINTR);
  282         return 0;
  283 }
  284 
  285 /*
  286  * Process incoming packets
  287  */
  288 static int
  289 smb_iod_recvall(struct smbiod *iod)
  290 {
  291         struct smb_vc *vcp = iod->iod_vc;
  292         struct proc *p = iod->iod_p;
  293         struct smb_rq *rqp;
  294         struct mbuf *m;
  295         u_char *hp;
  296         u_short mid;
  297         int error;
  298 
  299         switch (iod->iod_state) {
  300             case SMBIOD_ST_NOTCONN:
  301             case SMBIOD_ST_DEAD:
  302             case SMBIOD_ST_RECONNECT:
  303                 return 0;
  304             default:
  305                 break;
  306         }
  307         for (;;) {
  308                 m = NULL;
  309                 error = SMB_TRAN_RECV(vcp, &m, p);
  310                 if (error == EWOULDBLOCK)
  311                         break;
  312                 if (SMB_TRAN_FATAL(vcp, error)) {
  313                         smb_iod_dead(iod);
  314                         break;
  315                 }
  316                 if (error)
  317                         break;
  318                 if (m == NULL) {
  319                         SMBERROR("tran return NULL without error\n");
  320                         error = EPIPE;
  321                         continue;
  322                 }
  323                 m = m_pullup(m, SMB_HDRLEN);
  324                 if (m == NULL)
  325                         continue;       /* wait for a good packet */
  326                 /*
  327                  * Now we got an entire and possibly invalid SMB packet.
  328                  * Be careful while parsing it.
  329                  */
  330                 m_dumpm(m);
  331                 hp = mtod(m, u_char*);
  332                 if (bcmp(hp, SMB_SIGNATURE, SMB_SIGLEN) != 0) {
  333                         m_freem(m);
  334                         continue;
  335                 }
  336                 mid = SMB_HDRMID(hp);
  337                 SMBSDEBUG("mid %04x\n", (u_int)mid);
  338                 SMB_IOD_RQLOCK(iod);
  339                 TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
  340                         if (rqp->sr_mid != mid)
  341                                 continue;
  342                         SMBRQ_SLOCK(rqp);
  343                         if (rqp->sr_rp.md_top == NULL) {
  344                                 md_initm(&rqp->sr_rp, m);
  345                         } else {
  346                                 if (rqp->sr_flags & SMBR_MULTIPACKET) {
  347                                         md_append_record(&rqp->sr_rp, m);
  348                                 } else {
  349                                         SMBRQ_SUNLOCK(rqp);
  350                                         SMBERROR("duplicate response %d (ignored)\n", mid);
  351                                         break;
  352                                 }
  353                         }
  354                         SMBRQ_SUNLOCK(rqp);
  355                         smb_iod_rqprocessed(rqp, 0);
  356                         break;
  357                 }
  358                 SMB_IOD_RQUNLOCK(iod);
  359                 if (rqp == NULL) {
  360                         SMBERROR("drop resp with mid %d\n", (u_int)mid);
  361 /*                      smb_printrqlist(vcp);*/
  362                         m_freem(m);
  363                 }
  364         }
  365         /*
  366          * check for interrupts
  367          */
  368         SMB_IOD_RQLOCK(iod);
  369         TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
  370                 if (smb_proc_intr(rqp->sr_cred->scr_p)) {
  371                         smb_iod_rqprocessed(rqp, EINTR);
  372                 }
  373         }
  374         SMB_IOD_RQUNLOCK(iod);
  375         return 0;
  376 }
  377 
  378 int
  379 smb_iod_request(struct smbiod *iod, int event, void *ident)
  380 {
  381         struct smbiod_event *evp;
  382         int error;
  383 
  384         SMBIODEBUG("\n");
  385         evp = smb_zmalloc(sizeof(*evp), M_SMBIOD, M_WAITOK);
  386         evp->ev_type = event;
  387         evp->ev_ident = ident;
  388         SMB_IOD_EVLOCK(iod);
  389         STAILQ_INSERT_TAIL(&iod->iod_evlist, evp, ev_link);
  390         if ((event & SMBIOD_EV_SYNC) == 0) {
  391                 SMB_IOD_EVUNLOCK(iod);
  392                 smb_iod_wakeup(iod);
  393                 return 0;
  394         }
  395         smb_iod_wakeup(iod);
  396         msleep(evp, SMB_IOD_EVLOCKPTR(iod), PWAIT | PDROP, "90evw", 0);
  397         error = evp->ev_error;
  398         free(evp, M_SMBIOD);
  399         return error;
  400 }
  401 
  402 /*
  403  * Place request in the queue.
  404  * Request from smbiod have a high priority.
  405  */
  406 int
  407 smb_iod_addrq(struct smb_rq *rqp)
  408 {
  409         struct smb_vc *vcp = rqp->sr_vc;
  410         struct smbiod *iod = vcp->vc_iod;
  411         int error;
  412 
  413         SMBIODEBUG("\n");
  414         if (rqp->sr_cred->scr_p == iod->iod_p) {
  415                 rqp->sr_flags |= SMBR_INTERNAL;
  416                 SMB_IOD_RQLOCK(iod);
  417                 TAILQ_INSERT_HEAD(&iod->iod_rqlist, rqp, sr_link);
  418                 SMB_IOD_RQUNLOCK(iod);
  419                 for (;;) {
  420                         if (smb_iod_sendrq(iod, rqp) != 0) {
  421                                 smb_iod_dead(iod);
  422                                 break;
  423                         }
  424                         /*
  425                          * we don't need to lock state field here
  426                          */
  427                         if (rqp->sr_state != SMBRQ_NOTSENT)
  428                                 break;
  429                         tsleep(&iod->iod_flags, PWAIT, "90sndw", hz);
  430                 }
  431                 if (rqp->sr_lerror)
  432                         smb_iod_removerq(rqp);
  433                 return rqp->sr_lerror;
  434         }
  435 
  436         switch (iod->iod_state) {
  437             case SMBIOD_ST_NOTCONN:
  438                 return ENOTCONN;
  439             case SMBIOD_ST_DEAD:
  440                 error = smb_iod_request(vcp->vc_iod, SMBIOD_EV_CONNECT | SMBIOD_EV_SYNC, NULL);
  441                 if (error)
  442                         return error;
  443                 return EXDEV;
  444             default:
  445                 break;
  446         }
  447 
  448         SMB_IOD_RQLOCK(iod);
  449         for (;;) {
  450                 if (vcp->vc_maxmux == 0) {
  451                         SMBERROR("maxmux == 0\n");
  452                         break;
  453                 }
  454                 if (iod->iod_muxcnt < vcp->vc_maxmux)
  455                         break;
  456                 iod->iod_muxwant++;
  457                 msleep(&iod->iod_muxwant, SMB_IOD_RQLOCKPTR(iod),
  458                     PWAIT, "90mux", 0);
  459         }
  460         iod->iod_muxcnt++;
  461         TAILQ_INSERT_TAIL(&iod->iod_rqlist, rqp, sr_link);
  462         SMB_IOD_RQUNLOCK(iod);
  463         smb_iod_wakeup(iod);
  464         return 0;
  465 }
  466 
  467 int
  468 smb_iod_removerq(struct smb_rq *rqp)
  469 {
  470         struct smb_vc *vcp = rqp->sr_vc;
  471         struct smbiod *iod = vcp->vc_iod;
  472 
  473         SMBIODEBUG("\n");
  474         if (rqp->sr_flags & SMBR_INTERNAL) {
  475                 SMB_IOD_RQLOCK(iod);
  476                 TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
  477                 SMB_IOD_RQUNLOCK(iod);
  478                 return 0;
  479         }
  480         SMB_IOD_RQLOCK(iod);
  481         while (rqp->sr_flags & SMBR_XLOCK) {
  482                 rqp->sr_flags |= SMBR_XLOCKWANT;
  483                 msleep(rqp, SMB_IOD_RQLOCKPTR(iod), PWAIT, "90xrm", 0);
  484         }
  485         TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
  486         iod->iod_muxcnt--;
  487         if (iod->iod_muxwant) {
  488                 iod->iod_muxwant--;
  489                 wakeup(&iod->iod_muxwant);
  490         }
  491         SMB_IOD_RQUNLOCK(iod);
  492         return 0;
  493 }
  494 
  495 int
  496 smb_iod_waitrq(struct smb_rq *rqp)
  497 {
  498         struct smbiod *iod = rqp->sr_vc->vc_iod;
  499         int error;
  500 
  501         SMBIODEBUG("\n");
  502         if (rqp->sr_flags & SMBR_INTERNAL) {
  503                 for (;;) {
  504                         smb_iod_sendall(iod);
  505                         smb_iod_recvall(iod);
  506                         if (rqp->sr_rpgen != rqp->sr_rplast)
  507                                 break;
  508                         tsleep(&iod->iod_flags, PWAIT, "90irq", hz);
  509                 }
  510                 smb_iod_removerq(rqp);
  511                 return rqp->sr_lerror;
  512 
  513         }
  514         SMBRQ_SLOCK(rqp);
  515         if (rqp->sr_rpgen == rqp->sr_rplast)
  516                 msleep(&rqp->sr_state, SMBRQ_SLOCKPTR(rqp), PWAIT, "90wrq", 0);
  517         rqp->sr_rplast++;
  518         SMBRQ_SUNLOCK(rqp);
  519         error = rqp->sr_lerror;
  520         if (rqp->sr_flags & SMBR_MULTIPACKET) {
  521                 /*
  522                  * If request should stay in the list, then reinsert it
  523                  * at the end of queue so other waiters have chance to concur
  524                  */
  525                 SMB_IOD_RQLOCK(iod);
  526                 TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
  527                 TAILQ_INSERT_TAIL(&iod->iod_rqlist, rqp, sr_link);
  528                 SMB_IOD_RQUNLOCK(iod);
  529         } else
  530                 smb_iod_removerq(rqp);
  531         return error;
  532 }
  533 
  534 
  535 static int
  536 smb_iod_sendall(struct smbiod *iod)
  537 {
  538         struct smb_vc *vcp = iod->iod_vc;
  539         struct smb_rq *rqp;
  540         struct timespec ts, tstimeout;
  541         int herror;
  542 
  543         herror = 0;
  544         /*
  545          * Loop through the list of requests and send them if possible
  546          */
  547         SMB_IOD_RQLOCK(iod);
  548         TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
  549                 switch (rqp->sr_state) {
  550                     case SMBRQ_NOTSENT:
  551                         rqp->sr_flags |= SMBR_XLOCK;
  552                         SMB_IOD_RQUNLOCK(iod);
  553                         herror = smb_iod_sendrq(iod, rqp);
  554                         SMB_IOD_RQLOCK(iod);
  555                         rqp->sr_flags &= ~SMBR_XLOCK;
  556                         if (rqp->sr_flags & SMBR_XLOCKWANT) {
  557                                 rqp->sr_flags &= ~SMBR_XLOCKWANT;
  558                                 wakeup(rqp);
  559                         }
  560                         break;
  561                     case SMBRQ_SENT:
  562                         SMB_TRAN_GETPARAM(vcp, SMBTP_TIMEOUT, &tstimeout);
  563                         timespecadd(&tstimeout, &tstimeout);
  564                         getnanotime(&ts);
  565                         timespecsub(&ts, &tstimeout);
  566                         if (timespeccmp(&ts, &rqp->sr_timesent, >)) {
  567                                 smb_iod_rqprocessed(rqp, ETIMEDOUT);
  568                         }
  569                         break;
  570                     default:
  571                         break;
  572                 }
  573                 if (herror)
  574                         break;
  575         }
  576         SMB_IOD_RQUNLOCK(iod);
  577         if (herror == ENOTCONN)
  578                 smb_iod_dead(iod);
  579         return 0;
  580 }
  581 
  582 /*
  583  * "main" function for smbiod daemon
  584  */
  585 static __inline void
  586 smb_iod_main(struct smbiod *iod)
  587 {
  588 /*      struct smb_vc *vcp = iod->iod_vc;*/
  589         struct smbiod_event *evp;
  590 /*      struct timespec tsnow;*/
  591         int error;
  592 
  593         SMBIODEBUG("\n");
  594         error = 0;
  595 
  596         /*
  597          * Check all interesting events
  598          */
  599         for (;;) {
  600                 SMB_IOD_EVLOCK(iod);
  601                 evp = STAILQ_FIRST(&iod->iod_evlist);
  602                 if (evp == NULL) {
  603                         SMB_IOD_EVUNLOCK(iod);
  604                         break;
  605                 }
  606                 STAILQ_REMOVE_HEAD(&iod->iod_evlist, ev_link);
  607                 evp->ev_type |= SMBIOD_EV_PROCESSING;
  608                 SMB_IOD_EVUNLOCK(iod);
  609                 switch (evp->ev_type & SMBIOD_EV_MASK) {
  610                     case SMBIOD_EV_CONNECT:
  611                         iod->iod_state = SMBIOD_ST_RECONNECT;
  612                         evp->ev_error = smb_iod_connect(iod);
  613                         break;
  614                     case SMBIOD_EV_DISCONNECT:
  615                         evp->ev_error = smb_iod_disconnect(iod);
  616                         break;
  617                     case SMBIOD_EV_TREECONNECT:
  618                         evp->ev_error = smb_iod_treeconnect(iod, evp->ev_ident);
  619                         break;
  620                     case SMBIOD_EV_SHUTDOWN:
  621                         iod->iod_flags |= SMBIOD_SHUTDOWN;
  622                         break;
  623                     case SMBIOD_EV_NEWRQ:
  624                         break;
  625                 }
  626                 if (evp->ev_type & SMBIOD_EV_SYNC) {
  627                         SMB_IOD_EVLOCK(iod);
  628                         wakeup(evp);
  629                         SMB_IOD_EVUNLOCK(iod);
  630                 } else
  631                         free(evp, M_SMBIOD);
  632         }
  633 #if 0
  634         if (iod->iod_state == SMBIOD_ST_VCACTIVE) {
  635                 getnanotime(&tsnow);
  636                 timespecsub(&tsnow, &iod->iod_pingtimo);
  637                 if (timespeccmp(&tsnow, &iod->iod_lastrqsent, >)) {
  638                         smb_smb_echo(vcp, &iod->iod_scred);
  639                 }
  640         }
  641 #endif
  642         smb_iod_sendall(iod);
  643         smb_iod_recvall(iod);
  644         return;
  645 }
  646 
  647 #define kthread_create_compat   kthread_create2
  648 
  649 
  650 void
  651 smb_iod_thread(void *arg)
  652 {
  653         struct smbiod *iod = arg;
  654 
  655         smb_makescred(&iod->iod_scred, iod->iod_p, NULL);
  656         while ((iod->iod_flags & SMBIOD_SHUTDOWN) == 0) {
  657                 smb_iod_main(iod);
  658                 SMBIODEBUG("going to sleep for %d ticks\n", iod->iod_sleeptimo);
  659                 if (iod->iod_flags & SMBIOD_SHUTDOWN)
  660                         break;
  661                 tsleep(&iod->iod_flags, PWAIT, "90idle", iod->iod_sleeptimo);
  662         }
  663         kthread_exit(0);
  664 }
  665 
  666 int
  667 smb_iod_create(struct smb_vc *vcp)
  668 {
  669         struct smbiod *iod;
  670         int error;
  671 
  672         iod = smb_zmalloc(sizeof(*iod), M_SMBIOD, M_WAITOK);
  673         iod->iod_id = smb_iod_next++;
  674         iod->iod_state = SMBIOD_ST_NOTCONN;
  675         iod->iod_vc = vcp;
  676         iod->iod_sleeptimo = hz * SMBIOD_SLEEP_TIMO;
  677         iod->iod_pingtimo.tv_sec = SMBIOD_PING_TIMO;
  678         getnanotime(&iod->iod_lastrqsent);
  679         vcp->vc_iod = iod;
  680         smb_sl_init(&iod->iod_rqlock, "90rql");
  681         TAILQ_INIT(&iod->iod_rqlist);
  682         smb_sl_init(&iod->iod_evlock, "90evl");
  683         STAILQ_INIT(&iod->iod_evlist);
  684         error = kthread_create_compat(smb_iod_thread, iod, &iod->iod_p,
  685             RFNOWAIT, "smbiod%d", iod->iod_id);
  686         if (error) {
  687                 SMBERROR("can't start smbiod: %d", error);
  688                 free(iod, M_SMBIOD);
  689                 return error;
  690         }
  691         return 0;
  692 }
  693 
  694 int
  695 smb_iod_destroy(struct smbiod *iod)
  696 {
  697         smb_iod_request(iod, SMBIOD_EV_SHUTDOWN | SMBIOD_EV_SYNC, NULL);
  698         smb_sl_destroy(&iod->iod_rqlock);
  699         smb_sl_destroy(&iod->iod_evlock);
  700         free(iod, M_SMBIOD);
  701         return 0;
  702 }
  703 
  704 int
  705 smb_iod_init(void)
  706 {
  707         return 0;
  708 }
  709 
  710 int
  711 smb_iod_done(void)
  712 {
  713         return 0;
  714 }
  715 

Cache object: 88a31bc6a30fdfd0d572f894b53bfb21


[ 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.