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