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

Cache object: d4d4fe86f8dc2dd14590bbd1b166bc42


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