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 thread *td = iod->iod_td;
  109 
  110         if (vcp->vc_tdata == NULL)
  111                 return;
  112         SMB_TRAN_DISCONNECT(vcp, td);
  113         SMB_TRAN_DONE(vcp, td);
  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 thread *td = iod->iod_td;
  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 = 0;
  144 
  145         error = (int)SMB_TRAN_CREATE(vcp, td);
  146         if (error)
  147                 goto fail;
  148         SMBIODEBUG("tcreate\n");
  149         if (vcp->vc_laddr) {
  150                 error = (int)SMB_TRAN_BIND(vcp, vcp->vc_laddr, td);
  151                 if (error)
  152                         goto fail;
  153         }
  154         SMBIODEBUG("tbind\n");
  155         error = (int)SMB_TRAN_CONNECT(vcp, vcp->vc_paddr, td);
  156         if (error)
  157                 goto fail;
  158         SMB_TRAN_SETPARAM(vcp, SMBTP_SELECTID, &iod->iod_flags);
  159         iod->iod_state = SMBIOD_ST_TRANACTIVE;
  160         SMBIODEBUG("tconnect\n");
  161         /* vcp->vc_mid = 0;*/
  162         error = (int)smb_smb_negotiate(vcp, &iod->iod_scred);
  163         if (error)
  164                 goto fail;
  165         SMBIODEBUG("snegotiate\n");
  166         error = (int)smb_smb_ssnsetup(vcp, &iod->iod_scred);
  167         if (error)
  168                 goto fail;
  169         iod->iod_state = SMBIOD_ST_VCACTIVE;
  170         SMBIODEBUG("completed\n");
  171         smb_iod_invrq(iod);
  172         return (0);
  173 
  174  fail:
  175         smb_iod_dead(iod);
  176         return (error);
  177 }
  178 
  179 static int
  180 smb_iod_disconnect(struct smbiod *iod)
  181 {
  182         struct smb_vc *vcp = iod->iod_vc;
  183 
  184         SMBIODEBUG("\n");
  185         if (iod->iod_state == SMBIOD_ST_VCACTIVE) {
  186                 smb_smb_ssnclose(vcp, &iod->iod_scred);
  187                 iod->iod_state = SMBIOD_ST_TRANACTIVE;
  188         }
  189         vcp->vc_smbuid = SMB_UID_UNKNOWN;
  190         smb_iod_closetran(iod);
  191         iod->iod_state = SMBIOD_ST_NOTCONN;
  192         return 0;
  193 }
  194 
  195 static int
  196 smb_iod_treeconnect(struct smbiod *iod, struct smb_share *ssp)
  197 {
  198         int error;
  199 
  200         if (iod->iod_state != SMBIOD_ST_VCACTIVE) {
  201                 if (iod->iod_state != SMBIOD_ST_DEAD)
  202                         return ENOTCONN;
  203                 iod->iod_state = SMBIOD_ST_RECONNECT;
  204                 error = smb_iod_connect(iod);
  205                 if (error)
  206                         return error;
  207         }
  208         SMBIODEBUG("tree reconnect\n");
  209         SMBS_ST_LOCK(ssp);
  210         ssp->ss_flags |= SMBS_RECONNECTING;
  211         SMBS_ST_UNLOCK(ssp);
  212         error = smb_smb_treeconnect(ssp, &iod->iod_scred);
  213         SMBS_ST_LOCK(ssp);
  214         ssp->ss_flags &= ~SMBS_RECONNECTING;
  215         SMBS_ST_UNLOCK(ssp);
  216         wakeup(&ssp->ss_vcgenid);
  217         return error;
  218 }
  219 
  220 static int
  221 smb_iod_sendrq(struct smbiod *iod, struct smb_rq *rqp)
  222 {
  223         struct thread *td = iod->iod_td;
  224         struct smb_vc *vcp = iod->iod_vc;
  225         struct smb_share *ssp = rqp->sr_share;
  226         struct mbuf *m;
  227         int error;
  228 
  229         SMBIODEBUG("iod_state = %d\n", iod->iod_state);
  230         switch (iod->iod_state) {
  231             case SMBIOD_ST_NOTCONN:
  232                 smb_iod_rqprocessed(rqp, ENOTCONN);
  233                 return 0;
  234             case SMBIOD_ST_DEAD:
  235                 iod->iod_state = SMBIOD_ST_RECONNECT;
  236                 return 0;
  237             case SMBIOD_ST_RECONNECT:
  238                 return 0;
  239             default:
  240                 break;
  241         }
  242         if (rqp->sr_sendcnt == 0) {
  243 #ifdef movedtoanotherplace
  244                 if (vcp->vc_maxmux != 0 && iod->iod_muxcnt >= vcp->vc_maxmux)
  245                         return 0;
  246 #endif
  247                 le16enc(rqp->sr_rqtid, ssp ? ssp->ss_tid : SMB_TID_UNKNOWN);
  248                 le16enc(rqp->sr_rquid, vcp ? vcp->vc_smbuid : 0);
  249                 mb_fixhdr(&rqp->sr_rq);
  250                 if (vcp->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE)
  251                         smb_rq_sign(rqp);
  252         }
  253         if (rqp->sr_sendcnt++ > 5) {
  254                 rqp->sr_flags |= SMBR_RESTART;
  255                 smb_iod_rqprocessed(rqp, rqp->sr_lerror);
  256                 /*
  257                  * If all attempts to send a request failed, then
  258                  * something is seriously hosed.
  259                  */
  260                 return ENOTCONN;
  261         }
  262         SMBSDEBUG("M:%04x, P:%04x, U:%04x, T:%04x\n", rqp->sr_mid, 0, 0, 0);
  263         m_dumpm(rqp->sr_rq.mb_top);
  264         m = m_copym(rqp->sr_rq.mb_top, 0, M_COPYALL, M_TRYWAIT);
  265         error = rqp->sr_lerror = m ? SMB_TRAN_SEND(vcp, m, td) : ENOBUFS;
  266         if (error == 0) {
  267                 getnanotime(&rqp->sr_timesent);
  268                 iod->iod_lastrqsent = rqp->sr_timesent;
  269                 rqp->sr_flags |= SMBR_SENT;
  270                 rqp->sr_state = SMBRQ_SENT;
  271                 return 0;
  272         }
  273         /*
  274          * Check for fatal errors
  275          */
  276         if (SMB_TRAN_FATAL(vcp, error)) {
  277                 /*
  278                  * No further attempts should be made
  279                  */
  280                 return ENOTCONN;
  281         }
  282         if (smb_rq_intr(rqp))
  283                 smb_iod_rqprocessed(rqp, EINTR);
  284         return 0;
  285 }
  286 
  287 /*
  288  * Process incoming packets
  289  */
  290 static int
  291 smb_iod_recvall(struct smbiod *iod)
  292 {
  293         struct smb_vc *vcp = iod->iod_vc;
  294         struct thread *td = iod->iod_td;
  295         struct smb_rq *rqp;
  296         struct mbuf *m;
  297         u_char *hp;
  298         u_short mid;
  299         int error;
  300 
  301         switch (iod->iod_state) {
  302             case SMBIOD_ST_NOTCONN:
  303             case SMBIOD_ST_DEAD:
  304             case SMBIOD_ST_RECONNECT:
  305                 return 0;
  306             default:
  307                 break;
  308         }
  309         for (;;) {
  310                 m = NULL;
  311                 error = SMB_TRAN_RECV(vcp, &m, td);
  312                 if (error == EWOULDBLOCK)
  313                         break;
  314                 if (SMB_TRAN_FATAL(vcp, error)) {
  315                         smb_iod_dead(iod);
  316                         break;
  317                 }
  318                 if (error)
  319                         break;
  320                 if (m == NULL) {
  321                         SMBERROR("tran return NULL without error\n");
  322                         error = EPIPE;
  323                         continue;
  324                 }
  325                 m = m_pullup(m, SMB_HDRLEN);
  326                 if (m == NULL)
  327                         continue;       /* wait for a good packet */
  328                 /*
  329                  * Now we got an entire and possibly invalid SMB packet.
  330                  * Be careful while parsing it.
  331                  */
  332                 m_dumpm(m);
  333                 hp = mtod(m, u_char*);
  334                 if (bcmp(hp, SMB_SIGNATURE, SMB_SIGLEN) != 0) {
  335                         m_freem(m);
  336                         continue;
  337                 }
  338                 mid = SMB_HDRMID(hp);
  339                 SMBSDEBUG("mid %04x\n", (u_int)mid);
  340                 SMB_IOD_RQLOCK(iod);
  341                 TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
  342                         if (rqp->sr_mid != mid)
  343                                 continue;
  344                         SMBRQ_SLOCK(rqp);
  345                         if (rqp->sr_rp.md_top == NULL) {
  346                                 md_initm(&rqp->sr_rp, m);
  347                         } else {
  348                                 if (rqp->sr_flags & SMBR_MULTIPACKET) {
  349                                         md_append_record(&rqp->sr_rp, m);
  350                                 } else {
  351                                         SMBRQ_SUNLOCK(rqp);
  352                                         SMBERROR("duplicate response %d (ignored)\n", mid);
  353                                         break;
  354                                 }
  355                         }
  356                         SMBRQ_SUNLOCK(rqp);
  357                         smb_iod_rqprocessed(rqp, 0);
  358                         break;
  359                 }
  360                 SMB_IOD_RQUNLOCK(iod);
  361                 if (rqp == NULL) {
  362                         SMBERROR("drop resp with mid %d\n", (u_int)mid);
  363 /*                      smb_printrqlist(vcp);*/
  364                         m_freem(m);
  365                 }
  366         }
  367         /*
  368          * check for interrupts
  369          */
  370         SMB_IOD_RQLOCK(iod);
  371         TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
  372                 if (smb_td_intr(rqp->sr_cred->scr_td)) {
  373                         smb_iod_rqprocessed(rqp, EINTR);
  374                 }
  375         }
  376         SMB_IOD_RQUNLOCK(iod);
  377         return 0;
  378 }
  379 
  380 int
  381 smb_iod_request(struct smbiod *iod, int event, void *ident)
  382 {
  383         struct smbiod_event *evp;
  384         int error;
  385 
  386         SMBIODEBUG("\n");
  387         evp = smb_zmalloc(sizeof(*evp), M_SMBIOD, M_WAITOK);
  388         evp->ev_type = event;
  389         evp->ev_ident = ident;
  390         SMB_IOD_EVLOCK(iod);
  391         STAILQ_INSERT_TAIL(&iod->iod_evlist, evp, ev_link);
  392         if ((event & SMBIOD_EV_SYNC) == 0) {
  393                 SMB_IOD_EVUNLOCK(iod);
  394                 smb_iod_wakeup(iod);
  395                 return 0;
  396         }
  397         smb_iod_wakeup(iod);
  398         msleep(evp, SMB_IOD_EVLOCKPTR(iod), PWAIT | PDROP, "90evw", 0);
  399         error = evp->ev_error;
  400         free(evp, M_SMBIOD);
  401         return error;
  402 }
  403 
  404 /*
  405  * Place request in the queue.
  406  * Request from smbiod have a high priority.
  407  */
  408 int
  409 smb_iod_addrq(struct smb_rq *rqp)
  410 {
  411         struct smb_vc *vcp = rqp->sr_vc;
  412         struct smbiod *iod = vcp->vc_iod;
  413         int error;
  414 
  415         SMBIODEBUG("\n");
  416         if (rqp->sr_cred->scr_td != NULL &&
  417             rqp->sr_cred->scr_td->td_proc == iod->iod_p) {
  418                 rqp->sr_flags |= SMBR_INTERNAL;
  419                 SMB_IOD_RQLOCK(iod);
  420                 TAILQ_INSERT_HEAD(&iod->iod_rqlist, rqp, sr_link);
  421                 SMB_IOD_RQUNLOCK(iod);
  422                 for (;;) {
  423                         if (smb_iod_sendrq(iod, rqp) != 0) {
  424                                 smb_iod_dead(iod);
  425                                 break;
  426                         }
  427                         /*
  428                          * we don't need to lock state field here
  429                          */
  430                         if (rqp->sr_state != SMBRQ_NOTSENT)
  431                                 break;
  432                         tsleep(&iod->iod_flags, PWAIT, "90sndw", hz);
  433                 }
  434                 if (rqp->sr_lerror)
  435                         smb_iod_removerq(rqp);
  436                 return rqp->sr_lerror;
  437         }
  438 
  439         switch (iod->iod_state) {
  440             case SMBIOD_ST_NOTCONN:
  441                 return ENOTCONN;
  442             case SMBIOD_ST_DEAD:
  443                 error = smb_iod_request(vcp->vc_iod, SMBIOD_EV_CONNECT | SMBIOD_EV_SYNC, NULL);
  444                 if (error)
  445                         return error;
  446                 return EXDEV;
  447             default:
  448                 break;
  449         }
  450 
  451         SMB_IOD_RQLOCK(iod);
  452         for (;;) {
  453                 if (vcp->vc_maxmux == 0) {
  454                         SMBERROR("maxmux == 0\n");
  455                         break;
  456                 }
  457                 if (iod->iod_muxcnt < vcp->vc_maxmux)
  458                         break;
  459                 iod->iod_muxwant++;
  460                 msleep(&iod->iod_muxwant, SMB_IOD_RQLOCKPTR(iod),
  461                     PWAIT, "90mux", 0);
  462         }
  463         iod->iod_muxcnt++;
  464         TAILQ_INSERT_TAIL(&iod->iod_rqlist, rqp, sr_link);
  465         SMB_IOD_RQUNLOCK(iod);
  466         smb_iod_wakeup(iod);
  467         return 0;
  468 }
  469 
  470 int
  471 smb_iod_removerq(struct smb_rq *rqp)
  472 {
  473         struct smb_vc *vcp = rqp->sr_vc;
  474         struct smbiod *iod = vcp->vc_iod;
  475 
  476         SMBIODEBUG("\n");
  477         if (rqp->sr_flags & SMBR_INTERNAL) {
  478                 SMB_IOD_RQLOCK(iod);
  479                 TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
  480                 SMB_IOD_RQUNLOCK(iod);
  481                 return 0;
  482         }
  483         SMB_IOD_RQLOCK(iod);
  484         while (rqp->sr_flags & SMBR_XLOCK) {
  485                 rqp->sr_flags |= SMBR_XLOCKWANT;
  486                 msleep(rqp, SMB_IOD_RQLOCKPTR(iod), PWAIT, "90xrm", 0);
  487         }
  488         TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
  489         iod->iod_muxcnt--;
  490         if (iod->iod_muxwant) {
  491                 iod->iod_muxwant--;
  492                 wakeup(&iod->iod_muxwant);
  493         }
  494         SMB_IOD_RQUNLOCK(iod);
  495         return 0;
  496 }
  497 
  498 int
  499 smb_iod_waitrq(struct smb_rq *rqp)
  500 {
  501         struct smbiod *iod = rqp->sr_vc->vc_iod;
  502         int error;
  503 
  504         SMBIODEBUG("\n");
  505         if (rqp->sr_flags & SMBR_INTERNAL) {
  506                 for (;;) {
  507                         smb_iod_sendall(iod);
  508                         smb_iod_recvall(iod);
  509                         if (rqp->sr_rpgen != rqp->sr_rplast)
  510                                 break;
  511                         tsleep(&iod->iod_flags, PWAIT, "90irq", hz);
  512                 }
  513                 smb_iod_removerq(rqp);
  514                 return rqp->sr_lerror;
  515 
  516         }
  517         SMBRQ_SLOCK(rqp);
  518         if (rqp->sr_rpgen == rqp->sr_rplast)
  519                 msleep(&rqp->sr_state, SMBRQ_SLOCKPTR(rqp), PWAIT, "90wrq", 0);
  520         rqp->sr_rplast++;
  521         SMBRQ_SUNLOCK(rqp);
  522         error = rqp->sr_lerror;
  523         if (rqp->sr_flags & SMBR_MULTIPACKET) {
  524                 /*
  525                  * If request should stay in the list, then reinsert it
  526                  * at the end of queue so other waiters have chance to concur
  527                  */
  528                 SMB_IOD_RQLOCK(iod);
  529                 TAILQ_REMOVE(&iod->iod_rqlist, rqp, sr_link);
  530                 TAILQ_INSERT_TAIL(&iod->iod_rqlist, rqp, sr_link);
  531                 SMB_IOD_RQUNLOCK(iod);
  532         } else
  533                 smb_iod_removerq(rqp);
  534         return error;
  535 }
  536 
  537 
  538 static int
  539 smb_iod_sendall(struct smbiod *iod)
  540 {
  541         struct smb_vc *vcp = iod->iod_vc;
  542         struct smb_rq *rqp;
  543         struct timespec ts, tstimeout;
  544         int herror;
  545 
  546         herror = 0;
  547         /*
  548          * Loop through the list of requests and send them if possible
  549          */
  550         SMB_IOD_RQLOCK(iod);
  551         TAILQ_FOREACH(rqp, &iod->iod_rqlist, sr_link) {
  552                 switch (rqp->sr_state) {
  553                     case SMBRQ_NOTSENT:
  554                         rqp->sr_flags |= SMBR_XLOCK;
  555                         SMB_IOD_RQUNLOCK(iod);
  556                         herror = smb_iod_sendrq(iod, rqp);
  557                         SMB_IOD_RQLOCK(iod);
  558                         rqp->sr_flags &= ~SMBR_XLOCK;
  559                         if (rqp->sr_flags & SMBR_XLOCKWANT) {
  560                                 rqp->sr_flags &= ~SMBR_XLOCKWANT;
  561                                 wakeup(rqp);
  562                         }
  563                         break;
  564                     case SMBRQ_SENT:
  565                         SMB_TRAN_GETPARAM(vcp, SMBTP_TIMEOUT, &tstimeout);
  566                         timespecadd(&tstimeout, &tstimeout);
  567                         getnanotime(&ts);
  568                         timespecsub(&ts, &tstimeout);
  569                         if (timespeccmp(&ts, &rqp->sr_timesent, >)) {
  570                                 smb_iod_rqprocessed(rqp, ETIMEDOUT);
  571                         }
  572                         break;
  573                     default:
  574                         break;
  575                 }
  576                 if (herror)
  577                         break;
  578         }
  579         SMB_IOD_RQUNLOCK(iod);
  580         if (herror == ENOTCONN)
  581                 smb_iod_dead(iod);
  582         return 0;
  583 }
  584 
  585 /*
  586  * "main" function for smbiod daemon
  587  */
  588 static __inline void
  589 smb_iod_main(struct smbiod *iod)
  590 {
  591 /*      struct smb_vc *vcp = iod->iod_vc;*/
  592         struct smbiod_event *evp;
  593 /*      struct timespec tsnow;*/
  594         int error;
  595 
  596         SMBIODEBUG("\n");
  597         error = 0;
  598 
  599         /*
  600          * Check all interesting events
  601          */
  602         for (;;) {
  603                 SMB_IOD_EVLOCK(iod);
  604                 evp = STAILQ_FIRST(&iod->iod_evlist);
  605                 if (evp == NULL) {
  606                         SMB_IOD_EVUNLOCK(iod);
  607                         break;
  608                 }
  609                 STAILQ_REMOVE_HEAD(&iod->iod_evlist, ev_link);
  610                 evp->ev_type |= SMBIOD_EV_PROCESSING;
  611                 SMB_IOD_EVUNLOCK(iod);
  612                 switch (evp->ev_type & SMBIOD_EV_MASK) {
  613                     case SMBIOD_EV_CONNECT:
  614                         iod->iod_state = SMBIOD_ST_RECONNECT;
  615                         evp->ev_error = smb_iod_connect(iod);
  616                         break;
  617                     case SMBIOD_EV_DISCONNECT:
  618                         evp->ev_error = smb_iod_disconnect(iod);
  619                         break;
  620                     case SMBIOD_EV_TREECONNECT:
  621                         evp->ev_error = smb_iod_treeconnect(iod, evp->ev_ident);
  622                         break;
  623                     case SMBIOD_EV_SHUTDOWN:
  624                         iod->iod_flags |= SMBIOD_SHUTDOWN;
  625                         break;
  626                     case SMBIOD_EV_NEWRQ:
  627                         break;
  628                 }
  629                 if (evp->ev_type & SMBIOD_EV_SYNC) {
  630                         SMB_IOD_EVLOCK(iod);
  631                         wakeup(evp);
  632                         SMB_IOD_EVUNLOCK(iod);
  633                 } else
  634                         free(evp, M_SMBIOD);
  635         }
  636 #if 0
  637         if (iod->iod_state == SMBIOD_ST_VCACTIVE) {
  638                 getnanotime(&tsnow);
  639                 timespecsub(&tsnow, &iod->iod_pingtimo);
  640                 if (timespeccmp(&tsnow, &iod->iod_lastrqsent, >)) {
  641                         smb_smb_echo(vcp, &iod->iod_scred);
  642                 }
  643         }
  644 #endif
  645         smb_iod_sendall(iod);
  646         smb_iod_recvall(iod);
  647         return;
  648 }
  649 
  650 void
  651 smb_iod_thread(void *arg)
  652 {
  653         struct smbiod *iod = arg;
  654 
  655         mtx_lock(&Giant);
  656         /*
  657          * Here we assume that the thread structure will be the same
  658          * for an entire kthread (kproc, to be more precise) life.
  659          */
  660         iod->iod_td = curthread;
  661         smb_makescred(&iod->iod_scred, iod->iod_td, NULL);
  662         while ((iod->iod_flags & SMBIOD_SHUTDOWN) == 0) {
  663                 smb_iod_main(iod);
  664                 SMBIODEBUG("going to sleep for %d ticks\n", iod->iod_sleeptimo);
  665 /*              mtx_unlock(&Giant, MTX_DEF);*/
  666                 if (iod->iod_flags & SMBIOD_SHUTDOWN)
  667                         break;
  668                 tsleep(&iod->iod_flags, PWAIT, "90idle", iod->iod_sleeptimo);
  669         }
  670 /*      mtx_lock(&Giant, MTX_DEF);*/
  671         kthread_exit(0);
  672 }
  673 
  674 int
  675 smb_iod_create(struct smb_vc *vcp)
  676 {
  677         struct smbiod *iod;
  678         int error;
  679 
  680         iod = smb_zmalloc(sizeof(*iod), M_SMBIOD, M_WAITOK);
  681         iod->iod_id = smb_iod_next++;
  682         iod->iod_state = SMBIOD_ST_NOTCONN;
  683         iod->iod_vc = vcp;
  684         iod->iod_sleeptimo = hz * SMBIOD_SLEEP_TIMO;
  685         iod->iod_pingtimo.tv_sec = SMBIOD_PING_TIMO;
  686         getnanotime(&iod->iod_lastrqsent);
  687         vcp->vc_iod = iod;
  688         smb_sl_init(&iod->iod_rqlock, "90rql");
  689         TAILQ_INIT(&iod->iod_rqlist);
  690         smb_sl_init(&iod->iod_evlock, "90evl");
  691         STAILQ_INIT(&iod->iod_evlist);
  692         error = kthread_create(smb_iod_thread, iod, &iod->iod_p,
  693             RFNOWAIT, 0, "smbiod%d", iod->iod_id);
  694         if (error) {
  695                 SMBERROR("can't start smbiod: %d", error);
  696                 free(iod, M_SMBIOD);
  697                 return error;
  698         }
  699         return 0;
  700 }
  701 
  702 int
  703 smb_iod_destroy(struct smbiod *iod)
  704 {
  705         smb_iod_request(iod, SMBIOD_EV_SHUTDOWN | SMBIOD_EV_SYNC, NULL);
  706         smb_sl_destroy(&iod->iod_rqlock);
  707         smb_sl_destroy(&iod->iod_evlock);
  708         free(iod, M_SMBIOD);
  709         return 0;
  710 }
  711 
  712 int
  713 smb_iod_init(void)
  714 {
  715         return 0;
  716 }
  717 
  718 int
  719 smb_iod_done(void)
  720 {
  721         return 0;
  722 }
  723 

Cache object: 511f5f94b52cab254092b8852a560614


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