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_initiator/isc_sm.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) 2005-2010 Daniel Braniss <danny@cs.huji.ac.il>
    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  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  */
   27 /*
   28  | iSCSI - Session Manager
   29  | $Id: isc_sm.c 743 2009-08-08 10:54:53Z danny $
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include "opt_iscsi_initiator.h"
   36 
   37 #include <sys/param.h>
   38 #include <sys/kernel.h>
   39 #include <sys/conf.h>
   40 #include <sys/systm.h>
   41 #include <sys/malloc.h>
   42 #include <sys/ctype.h>
   43 #include <sys/errno.h>
   44 #include <sys/sysctl.h>
   45 #include <sys/file.h>
   46 #include <sys/uio.h>
   47 #include <sys/socketvar.h>
   48 #include <sys/socket.h>
   49 #include <sys/protosw.h>
   50 #include <sys/proc.h>
   51 #include <sys/ioccom.h>
   52 #include <sys/queue.h>
   53 #include <sys/kthread.h>
   54 #include <sys/syslog.h>
   55 #include <sys/mbuf.h>
   56 #include <sys/bus.h>
   57 #include <sys/sx.h>
   58 
   59 #include <cam/cam.h>
   60 #include <cam/cam_ccb.h>
   61 #include <cam/cam_sim.h>
   62 #include <cam/cam_xpt_sim.h>
   63 #include <cam/cam_periph.h>
   64 
   65 #include <dev/iscsi_initiator/iscsi.h>
   66 #include <dev/iscsi_initiator/iscsivar.h>
   67 
   68 static void
   69 _async(isc_session_t *sp, pduq_t *pq)
   70 {
   71      debug_called(8);
   72 
   73      iscsi_async(sp, pq);
   74 
   75      pdu_free(sp->isc, pq);
   76 }
   77 
   78 static void
   79 _reject(isc_session_t *sp, pduq_t *pq)
   80 {
   81      pduq_t     *opq;
   82      pdu_t      *pdu;
   83      reject_t   *reject;
   84      int        itt;
   85 
   86      debug_called(8);
   87      pdu = mtod(pq->mp, pdu_t *);
   88      itt = pdu->ipdu.bhs.itt;
   89      reject = &pq->pdu.ipdu.reject;
   90      sdebug(2, "itt=%x reason=0x%x", ntohl(itt), reject->reason);
   91      opq = i_search_hld(sp, itt, 0);
   92      if(opq != NULL)
   93           iscsi_reject(sp, opq, pq);
   94      else {
   95           switch(pq->pdu.ipdu.bhs.opcode) {
   96           case ISCSI_LOGOUT_CMD: // XXX: wasabi does this - can't figure out why
   97                sdebug(2, "ISCSI_LOGOUT_CMD ...");
   98                break;
   99           default:
  100                xdebug("%d] we lost something itt=%x",
  101                       sp->sid, ntohl(pq->pdu.ipdu.bhs.itt));
  102           }
  103      }
  104      pdu_free(sp->isc, pq);
  105 }
  106 
  107 static void
  108 _r2t(isc_session_t *sp, pduq_t *pq)
  109 {
  110      pduq_t     *opq;
  111 
  112      debug_called(8);
  113      opq = i_search_hld(sp, pq->pdu.ipdu.bhs.itt, 1);
  114      if(opq != NULL) {
  115           iscsi_r2t(sp, opq, pq);
  116      } 
  117      else {
  118           r2t_t         *r2t = &pq->pdu.ipdu.r2t;
  119 
  120           xdebug("%d] we lost something itt=%x r2tSN=%d bo=%x ddtl=%x",
  121                  sp->sid, ntohl(pq->pdu.ipdu.bhs.itt),
  122                  ntohl(r2t->r2tSN), ntohl(r2t->bo), ntohl(r2t->ddtl));
  123      }
  124      pdu_free(sp->isc, pq);
  125 }
  126 
  127 static void
  128 _scsi_rsp(isc_session_t *sp, pduq_t *pq)
  129 {
  130      pduq_t     *opq;
  131 
  132      debug_called(8);
  133      opq = i_search_hld(sp, pq->pdu.ipdu.bhs.itt, 0);
  134      debug(5, "itt=%x pq=%p opq=%p", ntohl(pq->pdu.ipdu.bhs.itt), pq, opq);
  135      if(opq != NULL) {
  136           iscsi_done(sp, opq, pq);
  137           i_acked_hld(sp, &pq->pdu);
  138      }
  139      else
  140           xdebug("%d] we lost something itt=%x",
  141                  sp->sid, ntohl(pq->pdu.ipdu.bhs.itt));
  142      pdu_free(sp->isc, pq);
  143 }
  144 
  145 static void
  146 _read_data(isc_session_t *sp, pduq_t *pq)
  147 {
  148      pduq_t             *opq;
  149 
  150      debug_called(8);
  151      opq = i_search_hld(sp, pq->pdu.ipdu.bhs.itt, 1);
  152      if(opq != NULL) {
  153           if(scsi_decap(sp, opq, pq) != 1) {
  154                i_remove_hld(sp, opq); // done
  155                pdu_free(sp->isc, opq);
  156           }
  157      }
  158      else
  159           xdebug("%d] we lost something itt=%x",
  160                  sp->sid, ntohl(pq->pdu.ipdu.bhs.itt));
  161      pdu_free(sp->isc, pq);
  162 }
  163 /*
  164  | this is a kludge,
  165  | the jury is not back with a veredict, user or kernel
  166  */
  167 static void
  168 _nop_out(isc_session_t *sp)
  169 {
  170      pduq_t     *pq;
  171      nop_out_t  *nop_out;
  172 
  173      debug_called(8);
  174 
  175      sdebug(4, "cws=%d", sp->cws);
  176      if(sp->cws == 0) {
  177           /*
  178            | only send a nop if window is closed.
  179            */
  180           if((pq = pdu_alloc(sp->isc, M_NOWAIT)) == NULL)
  181                // I guess we ran out of resources
  182                return;
  183           nop_out = &pq->pdu.ipdu.nop_out;
  184           nop_out->opcode = ISCSI_NOP_OUT;
  185           nop_out->itt = htonl(sp->sn.itt);
  186           nop_out->ttt = -1;
  187           nop_out->I = 1;
  188           nop_out->F = 1;
  189           if(isc_qout(sp, pq) != 0) {
  190                sdebug(1, "failed");
  191                pdu_free(sp->isc, pq);
  192           }
  193      }
  194 }
  195 
  196 static void
  197 _nop_in(isc_session_t *sp, pduq_t *pq)
  198 {
  199      pdu_t      *pp = &pq->pdu;
  200      nop_in_t   *nop_in = &pp->ipdu.nop_in;
  201      bhs_t      *bhs = &pp->ipdu.bhs;
  202 
  203      debug_called(8);
  204 
  205      sdebug(5, "itt=%x ttt=%x", htonl(nop_in->itt), htonl(nop_in->ttt));
  206      if(nop_in->itt == -1) {
  207           if(pp->ds_len != 0) {
  208                /*
  209                 | according to RFC 3720 this should be zero
  210                 | what to do if not?
  211                 */
  212                xdebug("%d] dslen not zero", sp->sid);
  213           }
  214           if(nop_in->ttt != -1) {
  215                nop_out_t        *nop_out;
  216                /*
  217                 | target wants a nop_out
  218                 */
  219                bhs->opcode = ISCSI_NOP_OUT;
  220                bhs->I = 1;
  221                bhs->F = 1;
  222                /*
  223                 | we are reusing the pdu, so bhs->ttt == nop_in->ttt;
  224                 | and need to zero out 'Reserved'
  225                 | small cludge here.
  226                 */
  227                nop_out = &pp->ipdu.nop_out;
  228                nop_out->sn.maxcmd = 0;
  229                memset(nop_out->mbz, 0, sizeof(nop_out->mbz));
  230                (void)isc_qout(sp, pq); //XXX: should check return?
  231                return;
  232           }
  233           //else {
  234                // just making noise?
  235                // see 10.9.1: target does not want and answer.
  236           //}
  237 
  238      } else
  239      if(nop_in->ttt == -1) {
  240           /*
  241            | it is an answer to a nop_in from us
  242            */
  243           if(nop_in->itt != -1) {
  244 #ifdef ISC_WAIT4PING
  245                // XXX: MUTEX please
  246                if(sp->flags & ISC_WAIT4PING) {
  247                     i_nqueue_rsp(sp, pq);
  248                     wakeup(&sp->rsp);
  249                     return;
  250                }
  251 #endif
  252           }
  253      }
  254      /*
  255       | drop it
  256       */
  257      pdu_free(sp->isc, pq);
  258      return;
  259 }
  260 
  261 int
  262 i_prepPDU(isc_session_t *sp, pduq_t *pq)
  263 {
  264      size_t     len, n;
  265      pdu_t      *pp = &pq->pdu;
  266      bhs_t      *bhp = &pp->ipdu.bhs;
  267 
  268      len = sizeof(bhs_t);
  269      if(pp->ahs_len) {
  270           len += pp->ahs_len;
  271           bhp->AHSLength =  pp->ahs_len / 4;
  272      }
  273      if(ISOK2DIG(sp->hdrDigest, pp))
  274           len += 4;
  275      if(pp->ds_len) {
  276           n = pp->ds_len;
  277           len += n;
  278 #if BYTE_ORDER == LITTLE_ENDIAN
  279           bhp->DSLength = ((n & 0x00ff0000) >> 16)
  280                | (n & 0x0000ff00)
  281                | ((n & 0x000000ff) << 16);
  282 #else
  283           bhp->DSLength = n;
  284 #endif
  285           if(len & 03) {
  286                n = 4 - (len & 03);
  287                len += n;
  288           }
  289           if(ISOK2DIG(sp->dataDigest, pp))
  290                len += 4;
  291      }
  292 
  293      pq->len = len;
  294      len -= sizeof(bhs_t);
  295      if(sp->opt.maxBurstLength && (len > sp->opt.maxBurstLength)) {
  296           xdebug("%d] pdu len=%zd > %d",
  297                  sp->sid, len, sp->opt.maxBurstLength);
  298           // XXX: when this happens it used to hang ...
  299           return E2BIG;
  300      }
  301      return 0;
  302 }
  303 
  304 int
  305 isc_qout(isc_session_t *sp, pduq_t *pq)
  306 {
  307      int error = 0;
  308 
  309      debug_called(8);
  310 
  311      if(pq->len == 0 && (error = i_prepPDU(sp, pq)))
  312           return error;
  313 
  314      if(pq->pdu.ipdu.bhs.I)
  315           i_nqueue_isnd(sp, pq);
  316      else
  317      if(pq->pdu.ipdu.data_out.opcode == ISCSI_WRITE_DATA)
  318           i_nqueue_wsnd(sp, pq);
  319      else
  320           i_nqueue_csnd(sp, pq);
  321 
  322      sdebug(5, "enqued: pq=%p", pq);
  323 
  324      mtx_lock(&sp->io_mtx);
  325      sp->flags |= ISC_OQNOTEMPTY;
  326      if(sp->flags & ISC_OWAITING)
  327           wakeup(&sp->flags);
  328      mtx_unlock(&sp->io_mtx);
  329 
  330      return error;
  331 }
  332 /*
  333  | called when a fullPhase is restarted
  334  */
  335 void
  336 ism_restart(isc_session_t *sp)
  337 {
  338      int lastcmd;
  339 
  340      sdebug(2, "restart ...");
  341      lastcmd = iscsi_requeue(sp);
  342 #if 0
  343      if(lastcmd != sp->sn.cmd) {
  344           sdebug(1, "resetting CmdSN to=%d (from %d)", lastcmd, sp->sn.cmd);
  345           sp->sn.cmd = lastcmd;
  346      }
  347 #endif
  348      mtx_lock(&sp->io_mtx);
  349      if(sp->flags & ISC_OWAITING) {
  350           wakeup(&sp->flags);
  351      }
  352      mtx_unlock(&sp->io_mtx);
  353 
  354      sdebug(2, "restarted sn.cmd=0x%x lastcmd=0x%x", sp->sn.cmd, lastcmd);
  355 }
  356 
  357 void
  358 ism_recv(isc_session_t *sp, pduq_t *pq)
  359 {
  360      bhs_t      *bhs;
  361      int        statSN;
  362 
  363      debug_called(8);
  364 
  365      bhs = &pq->pdu.ipdu.bhs;
  366      statSN = ntohl(bhs->OpcodeSpecificFields[1]);
  367 
  368 #ifdef notyet
  369      if(sp->sn.expCmd != sn->cmd) {
  370           sdebug(1, "we lost something ... exp=0x%x cmd=0x%x",
  371                  sn->expCmd, sn->cmd);
  372      }
  373 #endif
  374      sdebug(5, "opcode=0x%x itt=0x%x stat#0x%x maxcmd=0x%0x",
  375             bhs->opcode, ntohl(bhs->itt), statSN, sp->sn.maxCmd);
  376 
  377      switch(bhs->opcode) {
  378      case ISCSI_READ_DATA: {
  379           data_in_t     *cmd = &pq->pdu.ipdu.data_in;
  380 
  381           if(cmd->S == 0)
  382                break;
  383      }
  384 
  385      default:
  386           if(statSN > (sp->sn.stat + 1)) {
  387                sdebug(1, "we lost some rec=0x%x exp=0x%x",
  388                       statSN, sp->sn.stat);
  389                // XXX: must do some error recovery here.
  390           }
  391           sp->sn.stat = statSN;
  392      }
  393 
  394      switch(bhs->opcode) {
  395      case ISCSI_LOGIN_RSP:
  396      case ISCSI_TEXT_RSP:
  397      case ISCSI_LOGOUT_RSP:
  398           i_nqueue_rsp(sp, pq);
  399           wakeup(&sp->rsp);
  400           sdebug(3, "wakeup rsp");
  401           break;
  402 
  403      case ISCSI_NOP_IN:         _nop_in(sp, pq);        break;
  404      case ISCSI_SCSI_RSP:       _scsi_rsp(sp, pq);      break;
  405      case ISCSI_READ_DATA:      _read_data(sp, pq);     break;
  406      case ISCSI_R2T:            _r2t(sp, pq);           break;
  407      case ISCSI_REJECT:         _reject(sp, pq);        break;
  408      case ISCSI_ASYNC:          _async(sp, pq);         break;
  409 
  410      case ISCSI_TASK_RSP:
  411      default:
  412           sdebug(1, "opcode=0x%x itt=0x%x not implemented yet",
  413                  bhs->opcode, ntohl(bhs->itt));
  414           break;
  415      }
  416 }
  417 
  418 /*
  419  | go through the out queues looking for work
  420  | if either nothing to do, or window is closed
  421  | return.
  422  */
  423 static int
  424 proc_out(isc_session_t *sp)
  425 {
  426      sn_t       *sn = &sp->sn;
  427      pduq_t     *pq;
  428      int        error, which;
  429 
  430      debug_called(8);
  431      error = 0;
  432 
  433      while(sp->flags & ISC_LINK_UP) {
  434           pdu_t *pp;
  435           bhs_t *bhs;
  436           /*
  437            | check if there is outstanding work in:
  438            | 1- the Immediate queue
  439            | 2- the R2T queue
  440            | 3- the cmd queue, only if the command window allows it.
  441            */
  442           which = BIT(0) | BIT(1);
  443           if(SNA_GT(sn->cmd, sn->maxCmd) == 0) // if(sn->maxCmd - sn->smc + 1) > 0
  444                which |= BIT(2);
  445 
  446           sdebug(4, "which=%d sn->maxCmd=%d sn->cmd=%d", which, sn->maxCmd, sn->cmd);
  447 
  448           if((pq = i_dqueue_snd(sp, which)) == NULL)
  449                break;
  450           sdebug(4, "pq=%p", pq);
  451 
  452           pp = &pq->pdu;
  453           bhs = &pp->ipdu.bhs;
  454           switch(bhs->opcode) {
  455           case ISCSI_SCSI_CMD:
  456                sn->itt++;
  457                bhs->itt = htonl(sn->itt);
  458 
  459           case ISCSI_LOGIN_CMD:
  460           case ISCSI_TEXT_CMD:
  461           case ISCSI_LOGOUT_CMD:
  462           case ISCSI_SNACK:
  463           case ISCSI_NOP_OUT:
  464           case ISCSI_TASK_CMD:
  465                bhs->CmdSN = htonl(sn->cmd);
  466                if(bhs->I == 0)
  467                     sn->cmd++;
  468 
  469           case ISCSI_WRITE_DATA:
  470                bhs->ExpStSN = htonl(sn->stat + 1);
  471                break;
  472 
  473           default:
  474                // XXX: can this happen?
  475                xdebug("bad opcode=0x%x sn(cmd=0x%x expCmd=0x%x maxCmd=0x%x expStat=0x%x itt=0x%x)",
  476                       bhs->opcode,
  477                       sn->cmd, sn->expCmd, sn->maxCmd, sn->expStat, sn->itt);
  478                // XXX: and now?
  479           }
  480 
  481           sdebug(4, "opcode=0x%x sn(cmd=0x%x expCmd=0x%x maxCmd=0x%x expStat=0x%x itt=0x%x)",
  482                 bhs->opcode,
  483                 sn->cmd, sn->expCmd, sn->maxCmd, sn->expStat, sn->itt);
  484 
  485           if(bhs->opcode != ISCSI_NOP_OUT)
  486                /*
  487                 | enqued till ack is received
  488                 | note: sosend(...) does not mean the packet left
  489                 | the host so that freeing resources has to wait
  490                 */
  491                i_nqueue_hld(sp, pq);
  492 
  493           error = isc_sendPDU(sp, pq);
  494           if(bhs->opcode == ISCSI_NOP_OUT)
  495                pdu_free(sp->isc, pq);
  496           if(error) {
  497                xdebug("error=%d opcode=0x%x ccb=%p itt=%x",
  498                       error, bhs->opcode, pq->ccb, ntohl(bhs->itt));
  499                i_remove_hld(sp, pq);
  500                switch(error) {
  501                case EPIPE:
  502                     sp->flags &= ~ISC_LINK_UP;
  503 
  504                case EAGAIN:
  505                     xdebug("requed");
  506                     i_rqueue_pdu(sp, pq);
  507                     break;
  508 
  509                default:
  510                     if(pq->ccb) {
  511                          xdebug("back to cam");
  512                          pq->ccb->ccb_h.status |= CAM_REQUEUE_REQ; // some better error?
  513                          XPT_DONE(sp, pq->ccb);
  514                          pdu_free(sp->isc, pq);
  515                     }
  516                     else
  517                          xdebug("we lost it!");
  518                }
  519           }
  520      }
  521      return error;
  522 }
  523 
  524 /*
  525  | survives link breakdowns.
  526  */
  527 static void
  528 ism_out(void *vp)
  529 {
  530      isc_session_t      *sp = (isc_session_t *)vp;
  531      int                error;
  532 
  533      debug_called(8);
  534 
  535      sp->flags |= ISC_SM_RUNNING;
  536      sdebug(3, "started sp->flags=%x", sp->flags);
  537      do {
  538           if((sp->flags & ISC_HOLD) == 0) {
  539                error = proc_out(sp);
  540                if(error) {
  541                     sdebug(3, "error=%d", error);
  542                }
  543           }
  544           mtx_lock(&sp->io_mtx);
  545           if((sp->flags & ISC_LINK_UP) == 0) {
  546                sdebug(3, "ISC_LINK_UP==0, sp->flags=%x ", sp->flags);
  547                if(sp->soc != NULL)
  548                     sdebug(3, "so_state=%x", sp->soc->so_state);
  549                wakeup(&sp->soc);
  550           }
  551 
  552           if(!(sp->flags & ISC_OQNOTEMPTY)) {
  553                sp->flags |= ISC_OWAITING;
  554                if(msleep(&sp->flags, &sp->io_mtx, PRIBIO, "isc_proc", hz*30) == EWOULDBLOCK) {
  555                     if(sp->flags & ISC_CON_RUNNING)
  556                          _nop_out(sp);
  557                }
  558                sp->flags &= ~ISC_OWAITING;
  559           }
  560           sp->flags &= ~ISC_OQNOTEMPTY;
  561           mtx_unlock(&sp->io_mtx);
  562      } while(sp->flags & ISC_SM_RUN);
  563 
  564      sp->flags &= ~ISC_SM_RUNNING;
  565      sdebug(3, "dropped ISC_SM_RUNNING");
  566 
  567      wakeup(&sp->soc);
  568      wakeup(sp); // XXX: do we need this one?
  569 
  570 #if __FreeBSD_version >= 700000
  571      destroy_dev(sp->dev);
  572 #endif
  573 
  574      debug(3, "terminated sp=%p sp->sid=%d", sp, sp->sid);
  575 
  576 #if __FreeBSD_version >= 800000
  577      kproc_exit(0);
  578 #else
  579      kthread_exit(0);
  580 #endif
  581 }
  582 
  583 #if 0
  584 static int
  585 isc_dump_options(SYSCTL_HANDLER_ARGS)
  586 {
  587      int error;
  588      isc_session_t *sp;
  589      char       buf[1024], *bp;
  590 
  591      sp = (isc_session_t *)arg1;
  592      bp = buf;
  593      sprintf(bp, "targetname='%s'", sp->opt.targetName);
  594      bp += strlen(bp);
  595      sprintf(bp, " targetname='%s'", sp->opt.targetAddress);
  596      error = SYSCTL_OUT(req, buf, strlen(buf));
  597      return error;
  598 }
  599 #endif
  600 
  601 static int
  602 isc_dump_stats(SYSCTL_HANDLER_ARGS)
  603 {
  604      isc_session_t      *sp;
  605      struct isc_softc   *sc;
  606      char       buf[1024], *bp;
  607      int        error, n;
  608 
  609      sp = (isc_session_t *)arg1;
  610      sc = sp->isc;
  611 
  612      bp = buf;
  613      n = sizeof(buf);
  614      snprintf(bp, n, "recv=%d sent=%d", sp->stats.nrecv, sp->stats.nsent);
  615      bp += strlen(bp);
  616      n -= strlen(bp);
  617      snprintf(bp, n, " flags=0x%08x pdus-alloc=%d pdus-max=%d", 
  618                   sp->flags, sc->npdu_alloc, sc->npdu_max);
  619      bp += strlen(bp);
  620      n -= strlen(bp);
  621      snprintf(bp, n, " cws=%d cmd=%x exp=%x max=%x stat=%x itt=%x",
  622                   sp->cws, sp->sn.cmd, sp->sn.expCmd, sp->sn.maxCmd, sp->sn.stat, sp->sn.itt);
  623      error = SYSCTL_OUT(req, buf, strlen(buf));
  624      return error;
  625 }
  626 
  627 static int
  628 isc_sysctl_targetName(SYSCTL_HANDLER_ARGS)
  629 {
  630      char       buf[128], **cp;
  631      int        error;
  632 
  633      cp = (char **)arg1;
  634      snprintf(buf, sizeof(buf), "%s", *cp);
  635      error = SYSCTL_OUT(req, buf, strlen(buf));
  636      return error;
  637 }
  638      
  639 static int
  640 isc_sysctl_targetAddress(SYSCTL_HANDLER_ARGS)
  641 {
  642      char       buf[128], **cp;
  643      int        error;
  644 
  645      cp = (char **)arg1;
  646      snprintf(buf, sizeof(buf), "%s", *cp);
  647      error = SYSCTL_OUT(req, buf, strlen(buf));
  648      return error;
  649 }
  650      
  651 static void
  652 isc_add_sysctls(isc_session_t *sp)
  653 {
  654      debug_called(8);
  655      sdebug(6, "sid=%d %s", sp->sid, devtoname(sp->dev));
  656 
  657      sysctl_ctx_init(&sp->clist);
  658      sp->oid = SYSCTL_ADD_NODE(&sp->clist,
  659                                SYSCTL_CHILDREN(sp->isc->oid),
  660                                OID_AUTO,
  661                                devtoname(sp->dev) + 5, // iscsi0
  662                                CTLFLAG_RD,
  663                                0,
  664                                "initiator");
  665      SYSCTL_ADD_PROC(&sp->clist,
  666                      SYSCTL_CHILDREN(sp->oid),
  667                      OID_AUTO,
  668                      "targetname",
  669                      CTLTYPE_STRING | CTLFLAG_RD,
  670                      (void *)&sp->opt.targetName, 0,
  671                      isc_sysctl_targetName, "A", "target name");
  672 
  673      SYSCTL_ADD_PROC(&sp->clist,
  674                      SYSCTL_CHILDREN(sp->oid),
  675                      OID_AUTO,
  676                      "targeaddress",
  677                      CTLTYPE_STRING | CTLFLAG_RD,
  678                      (void *)&sp->opt.targetAddress, 0,
  679                      isc_sysctl_targetAddress, "A", "target address");
  680 
  681      SYSCTL_ADD_PROC(&sp->clist,
  682                      SYSCTL_CHILDREN(sp->oid),
  683                      OID_AUTO,
  684                      "stats",
  685                      CTLTYPE_STRING | CTLFLAG_RD,
  686                      (void *)sp, 0,
  687                      isc_dump_stats, "A", "statistics");
  688 
  689      SYSCTL_ADD_INT(&sp->clist,
  690                      SYSCTL_CHILDREN(sp->oid),
  691                      OID_AUTO,
  692                      "douio",
  693                      CTLFLAG_RW,
  694                      &sp->douio, 0, "enable uio on read");
  695 }
  696 
  697 void
  698 ism_stop(isc_session_t *sp)
  699 {
  700      struct isc_softc *sc = sp->isc;
  701      int        n;
  702 
  703      debug_called(8);
  704      sdebug(2, "terminating");
  705      /*
  706       | first stop the receiver
  707       */
  708      isc_stop_receiver(sp);
  709      /*
  710       | now stop the xmitter
  711       */
  712      n = 5;
  713      sp->flags &= ~ISC_SM_RUN;
  714      while(n-- && (sp->flags & ISC_SM_RUNNING)) {
  715           sdebug(2, "n=%d", n);
  716           wakeup(&sp->flags);
  717           tsleep(sp, PRIBIO, "-", 5*hz);
  718      }
  719      sdebug(2, "final n=%d", n);
  720      sp->flags &= ~ISC_FFPHASE;
  721      
  722      iscsi_cleanup(sp);
  723 
  724      (void)i_pdu_flush(sp);
  725 
  726      ic_destroy(sp);
  727 
  728      sx_xlock(&sc->unit_sx);
  729      free_unr(sc->unit, sp->sid);
  730      sx_xunlock(&sc->unit_sx);
  731 
  732      mtx_lock(&sc->isc_mtx);
  733      TAILQ_REMOVE(&sc->isc_sess, sp, sp_link);
  734      sc->nsess--;
  735      mtx_unlock(&sc->isc_mtx);
  736 
  737 #if __FreeBSD_version < 700000
  738      destroy_dev(sp->dev);
  739 #endif
  740 
  741      mtx_destroy(&sp->rsp_mtx);
  742      mtx_destroy(&sp->rsv_mtx);
  743      mtx_destroy(&sp->hld_mtx);
  744      mtx_destroy(&sp->snd_mtx);
  745      mtx_destroy(&sp->io_mtx);
  746 
  747      i_freeopt(&sp->opt);
  748 
  749      if(sysctl_ctx_free(&sp->clist))
  750           xdebug("sysctl_ctx_free failed");
  751 
  752      free(sp, M_ISCSI);
  753 }
  754 
  755 int
  756 ism_start(isc_session_t *sp)
  757 {
  758      debug_called(8);
  759     /*
  760      | now is a good time to do some initialization
  761      */
  762      TAILQ_INIT(&sp->rsp);
  763      TAILQ_INIT(&sp->rsv);
  764      TAILQ_INIT(&sp->csnd);
  765      TAILQ_INIT(&sp->isnd);
  766      TAILQ_INIT(&sp->wsnd);
  767      TAILQ_INIT(&sp->hld);
  768 
  769      mtx_init(&sp->rsv_mtx, "iscsi-rsv", NULL, MTX_DEF);
  770      mtx_init(&sp->rsp_mtx, "iscsi-rsp", NULL, MTX_DEF);
  771      mtx_init(&sp->snd_mtx, "iscsi-snd", NULL, MTX_DEF);
  772      mtx_init(&sp->hld_mtx, "iscsi-hld", NULL, MTX_DEF);
  773      mtx_init(&sp->io_mtx, "iscsi-io", NULL, MTX_DEF);
  774 
  775      isc_add_sysctls(sp);
  776 
  777      sp->flags |= ISC_SM_RUN;
  778 
  779      debug(4, "starting ism_proc: sp->sid=%d", sp->sid);
  780 
  781 #if __FreeBSD_version >= 800000
  782      return kproc_create(ism_out, sp, &sp->stp, 0, 0, "isc_out %d", sp->sid);
  783 #else
  784      return kthread_create(ism_out, sp, &sp->stp, 0, 0, "isc_out %d", sp->sid);
  785 #endif
  786 }

Cache object: 59cd221f76ecc8c0c3ebf8b511e4fbfe


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