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

Cache object: ab5a64422123b60a9cb746515feb28a7


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