1 /* $NetBSD: iscsi_send.c,v 1.1 2011/10/23 21:15:02 agc Exp $ */ 2 3 /*- 4 * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Wasabi Systems, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 #include "iscsi_globals.h" 32 33 #include <sys/file.h> 34 #include <sys/filedesc.h> 35 #include <sys/socket.h> 36 #include <sys/socketvar.h> 37 38 /*#define LUN_1 1 */ 39 40 /*****************************************************************************/ 41 42 /* 43 * my_soo_write: 44 * Replacement for soo_write with flag handling. 45 * 46 * Parameter: 47 * conn The connection 48 * u The uio descriptor 49 * 50 * Returns: 0 on success, else EIO. 51 */ 52 53 STATIC int 54 my_soo_write(connection_t *conn, struct uio *u) 55 { 56 struct socket *so = (struct socket *) conn->sock->f_data; 57 size_t resid = u->uio_resid; 58 int ret; 59 60 assert(resid != 0); 61 62 #if (__NetBSD_Version__ >= 300000000) 63 ret = sosend(so, NULL, u, NULL, NULL, 0, conn->threadobj); 64 #else 65 ret = sosend(so, NULL, u, NULL, NULL, 0); 66 #endif 67 68 DEB(99, ("soo_write done: len = %zu\n", u->uio_resid)); 69 70 if (ret != 0 || u->uio_resid) { 71 DEBC(conn, 0, ("Write failed sock %p (ret: %d, req: %zu, resid: %zu)\n", 72 conn->sock, ret, resid, u->uio_resid)); 73 handle_connection_error(conn, ISCSI_STATUS_SOCKET_ERROR, NO_LOGOUT); 74 return EIO; 75 } 76 return 0; 77 } 78 79 /*****************************************************************************/ 80 81 /* 82 * assign_connection: 83 * This function returns the connection to use for the next transaction. 84 * 85 * Parameter: The session 86 * 87 * Returns: The connection 88 */ 89 90 connection_t * 91 assign_connection(session_t *session, bool waitok) 92 { 93 connection_t *conn, *next; 94 95 do { 96 if ((conn = session->mru_connection) == NULL) { 97 return NULL; 98 } 99 next = conn; 100 do { 101 next = TAILQ_NEXT(next, connections); 102 if (next == NULL) { 103 next = TAILQ_FIRST(&session->conn_list); 104 } 105 } while (next != NULL && next != conn && 106 next->state != ST_FULL_FEATURE); 107 108 if (next->state != ST_FULL_FEATURE) { 109 if (waitok) { 110 tsleep(session, PRIBIO, "iscsi_assign_connection", 0); 111 next = TAILQ_FIRST(&session->conn_list); 112 } else { 113 return NULL; 114 } 115 } else { 116 session->mru_connection = next; 117 } 118 } while (next != NULL && next->state != ST_FULL_FEATURE); 119 120 return next; 121 } 122 123 124 /* 125 * reassign_tasks: 126 * Reassign pending commands to one of the still existing connections 127 * of a session. 128 * 129 * Parameter: 130 * oldconn The terminating connection 131 */ 132 133 STATIC void 134 reassign_tasks(connection_t *oldconn) 135 { 136 session_t *sess = oldconn->session; 137 connection_t *conn; 138 ccb_t *ccb; 139 pdu_t *pdu = NULL; 140 pdu_t *opdu; 141 int no_tm = 1; 142 int rc = 1; 143 144 if ((conn = assign_connection(sess, FALSE)) == NULL) { 145 DEB(1, ("Reassign_tasks of Session %d, connection %d failed, " 146 "no active connection\n", 147 sess->id, oldconn->id)); 148 return; 149 } 150 151 if (sess->ErrorRecoveryLevel >= 2) { 152 if (oldconn->loggedout == NOT_LOGGED_OUT) { 153 oldconn->loggedout = LOGOUT_SENT; 154 no_tm = send_logout(conn, oldconn, RECOVER_CONNECTION, TRUE); 155 oldconn->loggedout = (rc) ? LOGOUT_FAILED : LOGOUT_SUCCESS; 156 if (!oldconn->Time2Retain) { 157 DEBC(conn, 1, ("Time2Retain is zero, setting no_tm\n")); 158 no_tm = 1; 159 } 160 } else if (oldconn->loggedout == LOGOUT_SUCCESS) { 161 no_tm = 0; 162 } 163 if (!no_tm && oldconn->Time2Wait) { 164 DEBC(conn, 1, ("Time2Wait=%d, hz=%d, waiting...\n", 165 oldconn->Time2Wait, hz)); 166 tsleep(&no_tm, PRIBIO, "Time2Wait", oldconn->Time2Wait * hz); 167 } 168 } 169 170 DEBC(conn, 1, ("Reassign_tasks: Session %d, conn %d -> conn %d, no_tm=%d\n", 171 sess->id, oldconn->id, conn->id, no_tm)); 172 173 TAILQ_FOREACH(ccb, &oldconn->ccbs_waiting, chain) { 174 /* Copy PDU contents (PDUs are bound to connection) */ 175 if ((pdu = get_pdu(conn)) == NULL) { 176 break; 177 } 178 opdu = ccb->pdu_waiting; 179 *pdu = *opdu; 180 /* restore overwritten back ptr */ 181 pdu->connection = conn; 182 183 /* fixup saved UIO and IOVEC (regular one will be overwritten anyway) */ 184 pdu->save_uio.uio_iov = pdu->io_vec; 185 pdu->save_iovec [0].iov_base = &pdu->pdu; 186 187 if (conn->DataDigest && pdu->save_uio.uio_iovcnt > 1) { 188 if (pdu->save_iovec [2].iov_base == NULL) { 189 pdu->save_iovec [2].iov_base = &pdu->data_digest; 190 pdu->save_uio.uio_iovcnt = 3; 191 } else { 192 pdu->save_iovec [3].iov_base = &pdu->data_digest; 193 pdu->save_uio.uio_iovcnt = 4; 194 } 195 } 196 pdu->save_iovec [0].iov_len = 197 (conn->HeaderDigest) ? BHS_SIZE + 4 : BHS_SIZE; 198 199 ccb->pdu_waiting = pdu; 200 ccb->connection = conn; 201 ccb->num_timeouts = 0; 202 203 DEBC(conn, 1, ("CCB %p: Copied PDU %p to %p\n", 204 ccb, opdu, pdu)); 205 206 /* free the old PDU */ 207 opdu->temp_data = NULL; 208 free_pdu(opdu); 209 } 210 211 if (pdu == NULL) { 212 DEBC(conn, 1, ("Error while copying PDUs in reassign_tasks!\n")); 213 /* give up recovering, the other connection is screwed up as well... */ 214 while ((ccb = TAILQ_FIRST(&oldconn->ccbs_waiting)) != NULL) { 215 ccb->status = oldconn->terminating; 216 wake_ccb(ccb); 217 } 218 return; 219 } 220 221 while ((ccb = TAILQ_FIRST(&oldconn->ccbs_waiting)) != NULL) { 222 TAILQ_REMOVE(&oldconn->ccbs_waiting, ccb, chain); 223 TAILQ_INSERT_TAIL(&conn->ccbs_waiting, ccb, chain); 224 225 if (!no_tm) { 226 rc = send_task_management(conn, ccb, NULL, TASK_REASSIGN); 227 } 228 /* if we get an error on reassign, restart the original request */ 229 if (no_tm || rc) { 230 if (ccb->CmdSN < sess->ExpCmdSN) { 231 pdu = ccb->pdu_waiting; 232 233 /* update CmdSN */ 234 DEBC(conn, 1, ("Resend Updating CmdSN - old %d, new %d\n", 235 ccb->CmdSN, sess->CmdSN)); 236 ccb->CmdSN = sess->CmdSN; 237 if (!(pdu->pdu.Opcode & OP_IMMEDIATE)) { 238 sess->CmdSN++; 239 } 240 pdu->pdu.p.command.CmdSN = htonl(ccb->CmdSN); 241 } 242 resend_pdu(ccb); 243 } else { 244 SET_CCB_TIMEOUT(conn, ccb, COMMAND_TIMEOUT); 245 } 246 DEBC(conn, 1, ("Reassign ccb %p, no_tm=%d, rc=%d\n", 247 ccb, no_tm, rc)); 248 } 249 } 250 251 252 /* 253 * iscsi_send_thread: 254 * This thread services the send queue, writing the PDUs to the socket. 255 * It also handles the cleanup when the connection is terminated. 256 * 257 * Parameter: 258 * par The connection this thread services 259 */ 260 261 void 262 iscsi_send_thread(void *par) 263 { 264 connection_t *conn = (connection_t *) par; 265 session_t *sess; 266 ccb_t *ccb, *nccb; 267 pdu_t *pdu; 268 struct file *fp; 269 int s; 270 271 sess = conn->session; 272 /* so cleanup thread knows there's someone left */ 273 num_send_threads++; 274 275 do { 276 while (!conn->terminating) { 277 s = splbio(); 278 while (!conn->terminating && 279 (pdu = TAILQ_FIRST(&conn->pdus_to_send)) != NULL) { 280 TAILQ_REMOVE(&conn->pdus_to_send, pdu, send_chain); 281 pdu->flags &= ~PDUF_INQUEUE; 282 splx(s); 283 284 PERF_PDUSNAPB(pdu); 285 286 #ifdef ISCSI_DEBUG 287 if (!pdu->uio.uio_resid) { 288 DEBOUT(("uio.resid = 0 in iscsi_send_thread! pdu=%p\n", 289 pdu)); 290 assert(pdu->uio.uio_resid != 0); 291 } 292 #endif 293 /*DEB (99,("Send thread woke up, pdu = %x)\n", (int)pdu)); */ 294 295 #ifdef ISCSI_TEST_MODE 296 if (!test_mode_tx(conn, pdu)) { 297 if (!(pdu->flags & PDUF_NOUPDATE)) { 298 #endif 299 /* update ExpStatSN here to avoid discontinuities */ 300 /* and delays in updating target */ 301 pdu->pdu.p.command.ExpStatSN = 302 htonl(conn->StatSN_buf.ExpSN); 303 304 if (conn->HeaderDigest) 305 pdu->pdu.HeaderDigest = 306 gen_digest(&pdu->pdu, BHS_SIZE); 307 #ifdef ISCSI_TEST_MODE 308 } 309 #endif 310 my_soo_write(conn, &pdu->uio); 311 #ifdef ISCSI_TEST_MODE 312 } 313 #endif 314 PERF_PDUSNAPE(pdu); 315 316 if (pdu->disp <= PDUDISP_FREE) { 317 free_pdu(pdu); 318 } else { 319 pdu->flags &= ~PDUF_BUSY; 320 } 321 s = splbio(); 322 } 323 324 /*DEB (99,("Send thread done, waiting (conn->terminating = %d)\n", */ 325 /* conn->terminating)); */ 326 327 if (!conn->terminating) { 328 tsleep(&conn->pdus_to_send, PRIBIO, 329 "iscsisend", 0); 330 } 331 332 splx(s); 333 } 334 335 /* ------------------------------------------------------------------------ 336 * Here this thread takes over cleanup of the terminating connection. 337 * ------------------------------------------------------------------------ 338 */ 339 callout_stop(&conn->timeout); 340 conn->idle_timeout_val = CONNECTION_IDLE_TIMEOUT; 341 342 fp = conn->sock; 343 344 DEBC(conn, 9, ("Closing Socket %p\n", conn->sock)); 345 /* 346 * We must close the socket here to force the receive 347 * thread to wake up 348 */ 349 solock((struct socket *) fp->f_data); 350 soshutdown((struct socket *) fp->f_data, SHUT_RDWR); 351 sounlock((struct socket *) fp->f_data); 352 353 #if __NetBSD_Version__ > 500000000 354 mutex_enter(&fp->f_lock); 355 fp->f_count += 1; 356 mutex_exit(&fp->f_lock); 357 closef(fp); 358 #else 359 simple_lock(&fp->f_slock); 360 FILE_USE(fp); 361 closef(fp, NULL); 362 #endif 363 364 /* wake up any non-reassignable waiting CCBs */ 365 for (ccb = TAILQ_FIRST(&conn->ccbs_waiting); ccb != NULL; ccb = nccb) { 366 nccb = TAILQ_NEXT(ccb, chain); 367 if (!(ccb->flags & CCBF_REASSIGN) || ccb->pdu_waiting == NULL) { 368 ccb->status = conn->terminating; 369 wake_ccb(ccb); 370 } else { 371 callout_stop(&ccb->timeout); 372 ccb->num_timeouts = 0; 373 } 374 } 375 376 /* clean out anything left in send queue */ 377 while ((pdu = TAILQ_FIRST(&conn->pdus_to_send)) != NULL) { 378 TAILQ_REMOVE(&conn->pdus_to_send, pdu, send_chain); 379 pdu->flags &= ~(PDUF_INQUEUE | PDUF_BUSY); 380 /* if it's not attached to a waiting CCB, free it */ 381 if (pdu->owner == NULL || 382 pdu->owner->pdu_waiting != pdu) { 383 free_pdu(pdu); 384 } 385 } 386 387 /* If there's another connection available, transfer pending tasks */ 388 if (sess->active_connections && 389 TAILQ_FIRST(&conn->ccbs_waiting) != NULL) { 390 reassign_tasks (conn); 391 } else if (!conn->destroy && conn->Time2Wait) { 392 tsleep(&s, PRIBIO, "Time2Wait", conn->Time2Wait * hz); 393 } 394 /* notify event handlers of connection shutdown */ 395 add_event((conn->destroy) ? ISCSI_CONNECTION_TERMINATED 396 : ISCSI_RECOVER_CONNECTION, 397 sess->id, conn->id, conn->terminating); 398 399 if (!conn->destroy) 400 tsleep(conn, PRIBIO, "conn_idle", 0); 401 402 } while (!conn->destroy); 403 404 /* wake up anyone waiting for a PDU */ 405 wakeup(&conn->pdu_pool); 406 407 /* wake up any waiting CCBs */ 408 while ((ccb = TAILQ_FIRST(&conn->ccbs_waiting)) != NULL) { 409 ccb->status = conn->terminating; 410 wake_ccb(ccb); 411 /* NOTE: wake_ccb will remove the CCB from the queue */ 412 } 413 414 s = splbio(); 415 if (conn->in_session) { 416 conn->in_session = FALSE; 417 TAILQ_REMOVE(&sess->conn_list, conn, connections); 418 sess->mru_connection = TAILQ_FIRST(&sess->conn_list); 419 } 420 421 TAILQ_INSERT_TAIL(&cleanup_list, conn, connections); 422 splx(s); 423 424 wakeup(&cleanup_list); 425 426 conn->sendproc = NULL; 427 DEBC(conn, 5, ("Send thread exits\n")); 428 num_send_threads--; 429 kthread_exit(0); 430 } 431 432 433 /* 434 * send_pdu: 435 * Enqueue a PDU to be sent, and handle its disposition as well as 436 * the disposition of its associated CCB. 437 * 438 * Parameter: 439 * ccb The associated CCB. May be NULL if cdisp is CCBDISP_NOWAIT 440 * and pdisp is not PDUDISP_WAIT 441 * cdisp The CCB's disposition 442 * pdu The PDU 443 * pdisp The PDU's disposition 444 */ 445 446 STATIC void 447 send_pdu(ccb_t *ccb, pdu_t *pdu, ccb_disp_t cdisp, pdu_disp_t pdisp) 448 { 449 connection_t *conn = pdu->connection; 450 ccb_disp_t prev_cdisp = 0; 451 452 if (ccb != NULL) { 453 prev_cdisp = ccb->disp; 454 pdu->pdu.InitiatorTaskTag = ccb->ITT; 455 pdu->owner = ccb; 456 if (cdisp != CCBDISP_NOWAIT) 457 ccb->disp = cdisp; 458 } 459 460 pdu->disp = pdisp; 461 462 DEBC(conn, 10, ("Send_pdu: ccb=%p, pcd=%d, cdsp=%d, pdu=%p, pdsp=%d\n", 463 ccb, prev_cdisp, cdisp, pdu, pdisp)); 464 465 CS_BEGIN; 466 if (pdisp == PDUDISP_WAIT) { 467 ccb->pdu_waiting = pdu; 468 469 /* save UIO and IOVEC for retransmit */ 470 pdu->save_uio = pdu->uio; 471 memcpy(pdu->save_iovec, pdu->io_vec, sizeof(pdu->save_iovec)); 472 473 pdu->flags |= PDUF_BUSY; 474 } 475 /* Enqueue for sending */ 476 pdu->flags |= PDUF_INQUEUE; 477 478 if (pdu->flags & PDUF_PRIORITY) 479 TAILQ_INSERT_HEAD(&conn->pdus_to_send, pdu, send_chain); 480 else 481 TAILQ_INSERT_TAIL(&conn->pdus_to_send, pdu, send_chain); 482 483 wakeup(&conn->pdus_to_send); 484 485 if (cdisp != CCBDISP_NOWAIT) { 486 SET_CCB_TIMEOUT(conn, ccb, COMMAND_TIMEOUT); 487 488 if (prev_cdisp <= CCBDISP_NOWAIT) 489 TAILQ_INSERT_TAIL(&conn->ccbs_waiting, ccb, chain); 490 491 if (cdisp == CCBDISP_WAIT) 492 tsleep(ccb, PWAIT, "sendpdu", 0); 493 } 494 CS_END; 495 } 496 497 498 /* 499 * resend_pdu: 500 * Re-Enqueue a PDU that has apparently gotten lost. 501 * 502 * Parameter: 503 * ccb The associated CCB. 504 */ 505 506 void 507 resend_pdu(ccb_t *ccb) 508 { 509 connection_t *conn = ccb->connection; 510 pdu_t *pdu = ccb->pdu_waiting; 511 int s; 512 513 s = splbio (); 514 if (pdu == NULL || (pdu->flags & PDUF_BUSY)) { 515 splx (s); 516 return; 517 } 518 pdu->flags |= PDUF_BUSY; 519 splx (s); 520 521 /* restore UIO and IOVEC */ 522 pdu->uio = pdu->save_uio; 523 memcpy(pdu->io_vec, pdu->save_iovec, sizeof(pdu->io_vec)); 524 525 DEBC(conn, 8, ("ReSend_pdu ccb=%p, pdu=%p\n", ccb, pdu)); 526 527 s = splbio (); 528 529 /* Enqueue for sending */ 530 pdu->flags |= PDUF_INQUEUE; 531 532 if (pdu->flags & PDUF_PRIORITY) { 533 TAILQ_INSERT_HEAD(&conn->pdus_to_send, pdu, send_chain); 534 } else { 535 TAILQ_INSERT_TAIL(&conn->pdus_to_send, pdu, send_chain); 536 } 537 SET_CCB_TIMEOUT(conn, ccb, COMMAND_TIMEOUT); 538 splx (s); 539 540 wakeup(&conn->pdus_to_send); 541 } 542 543 544 /* 545 * setup_tx_uio: 546 * Initialize the uio structure for sending, including header, 547 * data (if present), padding, and Data Digest. 548 * Header Digest is generated in send thread. 549 * 550 * Parameter: 551 * pdu The PDU 552 * dsl The Data Segment Length 553 * data The data pointer 554 * read TRUE if this is a read operation 555 */ 556 557 STATIC void 558 setup_tx_uio(pdu_t *pdu, uint32_t dsl, void *data, bool read) 559 { 560 static uint8_t pad_bytes[4] = { 0 }; 561 struct uio *uio; 562 int i, pad, hlen; 563 connection_t *conn = pdu->connection; 564 565 DEB(99, ("SetupTxUio: dlen = %d, dptr: %p, read: %d\n", 566 dsl, data, read)); 567 568 if (!read && dsl) { 569 hton3(dsl, pdu->pdu.DataSegmentLength); 570 } 571 hlen = (conn->HeaderDigest) ? BHS_SIZE + 4 : BHS_SIZE; 572 573 pdu->io_vec[0].iov_base = &pdu->pdu; 574 pdu->io_vec[0].iov_len = hlen; 575 576 uio = &pdu->uio; 577 578 uio->uio_iov = pdu->io_vec; 579 uio->uio_iovcnt = 1; 580 uio->uio_rw = UIO_WRITE; 581 uio->uio_resid = hlen; 582 UIO_SETUP_SYSSPACE(uio); 583 584 if (!read && dsl) { 585 uio->uio_iovcnt++; 586 pdu->io_vec[1].iov_base = data; 587 pdu->io_vec[1].iov_len = dsl; 588 uio->uio_resid += dsl; 589 590 /* Pad to next multiple of 4 */ 591 pad = uio->uio_resid & 0x03; 592 if (pad) { 593 i = uio->uio_iovcnt++; 594 pad = 4 - pad; 595 pdu->io_vec[i].iov_base = pad_bytes; 596 pdu->io_vec[i].iov_len = pad; 597 uio->uio_resid += pad; 598 } 599 600 if (conn->DataDigest) { 601 pdu->data_digest = gen_digest_2(data, dsl, pad_bytes, pad); 602 i = uio->uio_iovcnt++; 603 pdu->io_vec[i].iov_base = &pdu->data_digest; 604 pdu->io_vec[i].iov_len = 4; 605 uio->uio_resid += 4; 606 } 607 } 608 } 609 610 /* 611 * init_login_pdu: 612 * Initialize the login PDU. 613 * 614 * Parameter: 615 * conn The connection 616 * pdu The PDU 617 */ 618 619 STATIC void 620 init_login_pdu(connection_t *conn, pdu_t *ppdu, bool next) 621 { 622 pdu_header_t *pdu = &ppdu->pdu; 623 login_isid_t *isid = (login_isid_t *) & pdu->LUN; 624 uint8_t c_phase; 625 626 pdu->Opcode = IOP_Login_Request | OP_IMMEDIATE; 627 628 if (next) { 629 c_phase = (pdu->Flags >> CSG_SHIFT) & SG_MASK; 630 pdu->Flags = FLAG_TRANSIT | (c_phase << CSG_SHIFT) | 631 NEXT_PHASE(c_phase); 632 } 633 634 memcpy(isid, &InitiatorISID, 6); 635 isid->TSIH = conn->session->TSIH; 636 637 pdu->p.login_req.CID = htons(conn->id); 638 pdu->p.login_req.CmdSN = htonl(conn->session->CmdSN); 639 } 640 641 642 /* 643 * negotiate_login: 644 * Control login negotiation. 645 * 646 * Parameter: 647 * conn The connection 648 * rx_pdu The received login response PDU 649 * tx_ccb The originally sent login CCB 650 */ 651 652 void 653 negotiate_login(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb) 654 { 655 int rc; 656 bool next = TRUE; 657 pdu_t *tx_pdu; 658 uint8_t c_phase; 659 660 if (rx_pdu->pdu.Flags & FLAG_TRANSIT) 661 c_phase = rx_pdu->pdu.Flags & SG_MASK; 662 else 663 c_phase = (rx_pdu->pdu.Flags >> CSG_SHIFT) & SG_MASK; 664 665 DEB(99, ("NegotiateLogin: Flags=%x Phase=%x\n", 666 rx_pdu->pdu.Flags, c_phase)); 667 668 if (c_phase == SG_FULL_FEATURE_PHASE) { 669 session_t *sess = conn->session; 670 671 if (!sess->TSIH) 672 sess->TSIH = ((login_isid_t *) &rx_pdu->pdu.LUN)->TSIH; 673 674 if (rx_pdu->temp_data != NULL) 675 assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, NULL); 676 677 /* negotiated values are now valid */ 678 set_negotiated_parameters(tx_ccb); 679 680 DEBC(conn, 5, ("Login Successful!\n")); 681 wake_ccb(tx_ccb); 682 return; 683 } 684 685 tx_pdu = get_pdu(conn); 686 if (tx_pdu == NULL) 687 return; 688 689 tx_pdu->pdu.Flags = c_phase << CSG_SHIFT; 690 691 switch (c_phase) { 692 case SG_SECURITY_NEGOTIATION: 693 rc = assemble_security_parameters(conn, tx_ccb, rx_pdu, tx_pdu); 694 if (rc < 0) 695 next = FALSE; 696 break; 697 698 case SG_LOGIN_OPERATIONAL_NEGOTIATION: 699 rc = assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, tx_pdu); 700 break; 701 702 default: 703 DEBOUT(("Invalid phase %x in negotiate_login\n", c_phase)); 704 rc = ISCSI_STATUS_TARGET_ERROR; 705 break; 706 } 707 708 if (rc > 0) { 709 tx_ccb->status = rc; 710 wake_ccb(tx_ccb); 711 free_pdu(tx_pdu); 712 } else { 713 init_login_pdu(conn, tx_pdu, next); 714 setup_tx_uio(tx_pdu, tx_pdu->temp_data_len, tx_pdu->temp_data, FALSE); 715 send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE); 716 } 717 } 718 719 720 /* 721 * init_text_pdu: 722 * Initialize the text PDU. 723 * 724 * Parameter: 725 * conn The connection 726 * ppdu The transmit PDU 727 * rx_pdu The received PDU if this is an unsolicited negotiation 728 */ 729 730 STATIC void 731 init_text_pdu(connection_t *conn, pdu_t *ppdu, pdu_t *rx_pdu) 732 { 733 pdu_header_t *pdu = &ppdu->pdu; 734 735 pdu->Opcode = IOP_Text_Request | OP_IMMEDIATE; 736 pdu->Flags = FLAG_FINAL; 737 738 if (rx_pdu != NULL) { 739 pdu->p.text_req.TargetTransferTag = 740 rx_pdu->pdu.p.text_rsp.TargetTransferTag; 741 pdu->LUN = rx_pdu->pdu.LUN; 742 } else 743 pdu->p.text_req.TargetTransferTag = 0xffffffff; 744 745 pdu->p.text_req.CmdSN = htonl(conn->session->CmdSN); 746 } 747 748 749 /* 750 * acknowledge_text: 751 * Acknowledge a continued login or text response. 752 * 753 * Parameter: 754 * conn The connection 755 * rx_pdu The received login/text response PDU 756 * tx_ccb The originally sent login/text request CCB 757 */ 758 759 void 760 acknowledge_text(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb) 761 { 762 pdu_t *tx_pdu; 763 764 tx_pdu = get_pdu(conn); 765 if (tx_pdu == NULL) 766 return; 767 768 if (rx_pdu != NULL && 769 (rx_pdu->pdu.Opcode & OPCODE_MASK) == IOP_Login_Request) 770 init_login_pdu(conn, tx_pdu, FALSE); 771 else 772 init_text_pdu(conn, tx_pdu, rx_pdu); 773 774 setup_tx_uio(tx_pdu, 0, NULL, FALSE); 775 send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE); 776 } 777 778 779 /* 780 * start_text_negotiation: 781 * Handle target request to negotiate (via asynch event) 782 * 783 * Parameter: 784 * conn The connection 785 */ 786 787 void 788 start_text_negotiation(connection_t *conn) 789 { 790 pdu_t *pdu; 791 ccb_t *ccb; 792 793 ccb = get_ccb(conn, TRUE); 794 pdu = get_pdu(conn); 795 if (ccb == NULL || pdu == NULL) 796 return; 797 798 if (init_text_parameters(conn, ccb)) { 799 free_ccb(ccb); 800 free_pdu(pdu); 801 return; 802 } 803 804 init_text_pdu(conn, pdu, NULL); 805 setup_tx_uio(pdu, 0, NULL, FALSE); 806 send_pdu(ccb, pdu, CCBDISP_FREE, PDUDISP_WAIT); 807 } 808 809 810 /* 811 * negotiate_text: 812 * Handle received text negotiation. 813 * 814 * Parameter: 815 * conn The connection 816 * rx_pdu The received text response PDU 817 * tx_ccb The original CCB 818 */ 819 820 void 821 negotiate_text(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb) 822 { 823 int rc; 824 pdu_t *tx_pdu; 825 826 if (tx_ccb->flags & CCBF_SENDTARGET) { 827 if (!(rx_pdu->pdu.Flags & FLAG_FINAL)) { 828 handle_connection_error(conn, ISCSI_STATUS_PROTOCOL_ERROR, 829 LOGOUT_CONNECTION); 830 return; 831 } 832 /* transfer ownership of text to CCB */ 833 tx_ccb->text_data = rx_pdu->temp_data; 834 tx_ccb->text_len = rx_pdu->temp_data_len; 835 rx_pdu->temp_data = NULL; 836 wake_ccb(tx_ccb); 837 } else { 838 if (!(rx_pdu->pdu.Flags & FLAG_FINAL)) 839 tx_pdu = get_pdu(conn); 840 else 841 tx_pdu = NULL; 842 843 rc = assemble_negotiation_parameters(conn, tx_ccb, rx_pdu, tx_pdu); 844 if (rc) { 845 if (tx_pdu != NULL) 846 free_pdu(tx_pdu); 847 848 handle_connection_error(conn, rc, LOGOUT_CONNECTION); 849 } else if (tx_pdu != NULL) { 850 init_text_pdu(conn, tx_pdu, rx_pdu); 851 setup_tx_uio(tx_pdu, tx_pdu->temp_data_len, tx_pdu->temp_data, 852 FALSE); 853 send_pdu(tx_ccb, tx_pdu, CCBDISP_NOWAIT, PDUDISP_FREE); 854 } else { 855 set_negotiated_parameters(tx_ccb); 856 wake_ccb(tx_ccb); 857 } 858 } 859 } 860 861 862 /* 863 * send_send_targets: 864 * Send out a SendTargets text request. 865 * The result is stored in the fields in the session structure. 866 * 867 * Parameter: 868 * session The session 869 * key The text key to use 870 * 871 * Returns: 0 on success, else an error code. 872 */ 873 874 int 875 send_send_targets(session_t *session, uint8_t *key) 876 { 877 ccb_t *ccb; 878 pdu_t *pdu; 879 int rc = 0; 880 connection_t *conn; 881 882 DEB(9, ("Send_send_targets\n")); 883 884 conn = assign_connection(session, TRUE); 885 if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE) 886 return (conn != NULL && conn->terminating) ? conn->terminating 887 : ISCSI_STATUS_CONNECTION_FAILED; 888 889 ccb = get_ccb(conn, TRUE); 890 pdu = get_pdu(conn); 891 /* can only happen if terminating... */ 892 if (ccb == NULL || pdu == NULL) 893 return conn->terminating; 894 895 ccb->flags |= CCBF_SENDTARGET; 896 897 if ((rc = assemble_send_targets(pdu, key)) != 0) { 898 free_ccb(ccb); 899 free_pdu(pdu); 900 return rc; 901 } 902 903 init_text_pdu(conn, pdu, NULL); 904 905 setup_tx_uio(pdu, pdu->temp_data_len, pdu->temp_data, FALSE); 906 send_pdu(ccb, pdu, CCBDISP_WAIT, PDUDISP_WAIT); 907 908 rc = ccb->status; 909 if (!rc) { 910 /* transfer ownership of data */ 911 session->target_list = ccb->text_data; 912 session->target_list_len = ccb->text_len; 913 ccb->text_data = NULL; 914 } 915 free_ccb(ccb); 916 return rc; 917 } 918 919 920 /* 921 * send_nop_out: 922 * Send nop out request. 923 * 924 * Parameter: 925 * conn The connection 926 * rx_pdu The received Nop-In PDU 927 * 928 * Returns: 0 on success, else an error code. 929 */ 930 931 int 932 send_nop_out(connection_t *conn, pdu_t *rx_pdu) 933 { 934 ccb_t *ccb; 935 pdu_t *ppdu; 936 pdu_header_t *pdu; 937 938 DEBC(conn, 10, ("Send NOP_Out rx_pdu=%p\n", rx_pdu)); 939 940 if (rx_pdu != NULL) { 941 ccb = NULL; 942 ppdu = get_pdu(conn); 943 if (ppdu == NULL) 944 return 1; 945 } else { 946 ccb = get_ccb(conn, FALSE); 947 if (ccb == NULL) { 948 DEBOUT(("Can't get CCB in send_nop_out\n")); 949 return 1; 950 } 951 ppdu = get_pdu_c(conn, FALSE); 952 if (ppdu == NULL) { 953 free_ccb(ccb); 954 DEBOUT(("Can't get PDU in send_nop_out\n")); 955 return 1; 956 } 957 } 958 959 pdu = &ppdu->pdu; 960 pdu->Flags = FLAG_FINAL; 961 pdu->Opcode = IOP_NOP_Out | OP_IMMEDIATE; 962 963 if (rx_pdu != NULL) { 964 pdu->p.nop_out.TargetTransferTag = 965 rx_pdu->pdu.p.nop_in.TargetTransferTag; 966 pdu->InitiatorTaskTag = rx_pdu->pdu.InitiatorTaskTag; 967 pdu->p.nop_out.CmdSN = htonl(conn->session->CmdSN); 968 pdu->LUN = rx_pdu->pdu.LUN; 969 } else { 970 pdu->p.nop_out.TargetTransferTag = 0xffffffff; 971 ccb->CmdSN = ccb->session->CmdSN; 972 pdu->p.nop_out.CmdSN = htonl(ccb->CmdSN); 973 } 974 975 setup_tx_uio(ppdu, 0, NULL, FALSE); 976 send_pdu(ccb, ppdu, (rx_pdu != NULL) ? CCBDISP_NOWAIT : CCBDISP_FREE, 977 PDUDISP_FREE); 978 return 0; 979 } 980 981 982 /* 983 * snack_missing: 984 * Send SNACK request for missing data. 985 * 986 * Parameter: 987 * conn The connection 988 * ccb The task's CCB (for Data NAK only) 989 * type The SNACK type 990 * BegRun The BegRun field 991 * RunLength The RunLength field 992 */ 993 994 void 995 snack_missing(connection_t *conn, ccb_t *ccb, uint8_t type, 996 uint32_t BegRun, uint32_t RunLength) 997 { 998 pdu_t *ppdu; 999 pdu_header_t *pdu; 1000 1001 PDEBC(conn, 1, ("SNACK Missing type = %d, BegRun %d RunLength %d\n", 1002 type, BegRun, RunLength)); 1003 1004 ppdu = get_pdu(conn); 1005 if (ppdu == NULL) 1006 return; 1007 pdu = &ppdu->pdu; 1008 pdu->Opcode = IOP_SNACK_Request; 1009 pdu->Flags = FLAG_FINAL | type; 1010 1011 pdu->InitiatorTaskTag = (type == SNACK_DATA_NAK) ? ccb->ITT : 0xffffffff; 1012 pdu->p.snack.TargetTransferTag = 0xffffffff; 1013 pdu->p.snack.BegRun = htonl(BegRun); 1014 pdu->p.snack.RunLength = htonl(RunLength); 1015 1016 ppdu->flags = PDUF_PRIORITY; 1017 1018 setup_tx_uio(ppdu, 0, NULL, FALSE); 1019 send_pdu(NULL, ppdu, CCBDISP_NOWAIT, PDUDISP_FREE); 1020 } 1021 1022 1023 /* 1024 * send_snack: 1025 * Send SNACK request. 1026 * 1027 * Parameter: 1028 * conn The connection 1029 * rx_pdu The received data in PDU 1030 * tx_ccb The original command CCB (required for Data ACK only) 1031 * type The SNACK type 1032 * 1033 * Returns: 0 on success, else an error code. 1034 */ 1035 1036 void 1037 send_snack(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb, uint8_t type) 1038 { 1039 pdu_t *ppdu; 1040 pdu_header_t *pdu; 1041 1042 PDEBC(conn, 1, ("Send SNACK type = %d\n", type)); 1043 1044 ppdu = get_pdu(conn); 1045 if (ppdu == NULL) 1046 return; 1047 pdu = &ppdu->pdu; 1048 pdu->Opcode = IOP_SNACK_Request; 1049 pdu->Flags = FLAG_FINAL | type; 1050 1051 switch (type) { 1052 case SNACK_DATA_NAK: 1053 pdu->InitiatorTaskTag = rx_pdu->pdu.InitiatorTaskTag; 1054 pdu->p.snack.TargetTransferTag = 0xffffffff; 1055 pdu->p.snack.BegRun = rx_pdu->pdu.p.data_in.DataSN; 1056 pdu->p.snack.RunLength = htonl(1); 1057 break; 1058 1059 case SNACK_STATUS_NAK: 1060 pdu->InitiatorTaskTag = 0xffffffff; 1061 pdu->p.snack.TargetTransferTag = 0xffffffff; 1062 pdu->p.snack.BegRun = rx_pdu->pdu.p.response.StatSN; 1063 pdu->p.snack.RunLength = htonl(1); 1064 break; 1065 1066 case SNACK_DATA_ACK: 1067 pdu->InitiatorTaskTag = 0xffffffff; 1068 pdu->p.snack.TargetTransferTag = 1069 rx_pdu->pdu.p.data_in.TargetTransferTag; 1070 pdu->p.snack.BegRun = tx_ccb->DataSN_buf.ExpSN; 1071 pdu->p.snack.RunLength = 0; 1072 break; 1073 1074 default: 1075 DEBOUT(("Invalid type %d in send_snack\n", type)); 1076 return; 1077 } 1078 1079 pdu->LUN = rx_pdu->pdu.LUN; 1080 1081 ppdu->flags = PDUF_PRIORITY; 1082 1083 setup_tx_uio(ppdu, 0, NULL, FALSE); 1084 send_pdu(NULL, ppdu, CCBDISP_NOWAIT, PDUDISP_FREE); 1085 } 1086 1087 1088 /* 1089 * send_login: 1090 * Send login request. 1091 * 1092 * Parameter: 1093 * conn The connection 1094 * par The login parameters (for negotiation) 1095 * 1096 * Returns: 0 on success, else an error code. 1097 */ 1098 1099 int 1100 send_login(connection_t *conn) 1101 { 1102 ccb_t *ccb; 1103 pdu_t *pdu; 1104 int rc; 1105 1106 DEBC(conn, 9, ("Send_login\n")); 1107 ccb = get_ccb(conn, TRUE); 1108 pdu = get_pdu(conn); 1109 1110 /* only if terminating (which couldn't possibly happen here, but...) */ 1111 if (ccb == NULL || pdu == NULL) { 1112 return conn->terminating; 1113 } 1114 if ((rc = assemble_login_parameters(conn, ccb, pdu)) >= 0) { 1115 init_login_pdu(conn, pdu, !rc); 1116 setup_tx_uio(pdu, pdu->temp_data_len, pdu->temp_data, FALSE); 1117 send_pdu(ccb, pdu, CCBDISP_WAIT, PDUDISP_FREE); 1118 rc = ccb->status; 1119 } else { 1120 free_pdu(pdu); 1121 } 1122 free_ccb(ccb); 1123 return rc; 1124 } 1125 1126 1127 /* 1128 * send_logout: 1129 * Send logout request. 1130 * NOTE: This function does not wait for the logout to complete. 1131 * 1132 * Parameter: 1133 * conn The connection 1134 * refconn The referenced connection 1135 * reason The reason code 1136 * wait Wait for completion if TRUE 1137 * 1138 * Returns: 0 on success (logout sent), else an error code. 1139 */ 1140 1141 int 1142 send_logout(connection_t *conn, connection_t *refconn, int reason, 1143 bool wait) 1144 { 1145 ccb_t *ccb; 1146 pdu_t *ppdu; 1147 pdu_header_t *pdu; 1148 1149 DEBC(conn, 5, ("Send_logout\n")); 1150 ccb = get_ccb(conn, TRUE); 1151 ppdu = get_pdu(conn); 1152 /* can only happen if terminating... */ 1153 if (ccb == NULL || ppdu == NULL) 1154 return conn->terminating; 1155 1156 pdu = &ppdu->pdu; 1157 pdu->Opcode = IOP_Logout_Request | OP_IMMEDIATE; 1158 1159 pdu->Flags = FLAG_FINAL | reason; 1160 ccb->CmdSN = conn->session->CmdSN; 1161 pdu->p.logout_req.CmdSN = htonl(ccb->CmdSN); 1162 if (reason > 0) 1163 pdu->p.logout_req.CID = htons(refconn->id); 1164 1165 ccb->par = refconn; 1166 if (refconn != conn) { 1167 ccb->flags |= CCBF_OTHERCONN; 1168 } else { 1169 conn->state = ST_LOGOUT_SENT; 1170 conn->loggedout = LOGOUT_SENT; 1171 } 1172 1173 setup_tx_uio(ppdu, 0, NULL, FALSE); 1174 1175 send_pdu(ccb, ppdu, (wait) ? CCBDISP_WAIT : CCBDISP_FREE, PDUDISP_FREE); 1176 1177 if (wait) { 1178 int rc = ccb->status; 1179 free_ccb (ccb); 1180 return rc; 1181 } 1182 return 0; 1183 } 1184 1185 1186 /* 1187 * send_task_management: 1188 * Send task management request. 1189 * 1190 * Parameter: 1191 * conn The connection 1192 * ref_ccb The referenced command (NULL if none) 1193 * xs The scsipi command structure (NULL if not a scsipi request) 1194 * function The function code 1195 * 1196 * Returns: 0 on success, else an error code. 1197 */ 1198 1199 int 1200 send_task_management(connection_t *conn, ccb_t *ref_ccb, struct scsipi_xfer *xs, 1201 int function) 1202 { 1203 ccb_t *ccb; 1204 pdu_t *ppdu; 1205 pdu_header_t *pdu; 1206 1207 DEBC(conn, 5, ("Send_task_management, ref_ccb=%p, func = %d\n", 1208 ref_ccb, function)); 1209 1210 if (function == TASK_REASSIGN && conn->session->ErrorRecoveryLevel < 2) 1211 return ISCSI_STATUS_CANT_REASSIGN; 1212 1213 ccb = get_ccb(conn, xs == NULL); 1214 ppdu = get_pdu(conn); 1215 /* can only happen if terminating... */ 1216 if (ccb == NULL || ppdu == NULL) 1217 return conn->terminating; 1218 1219 ccb->xs = xs; 1220 1221 pdu = &ppdu->pdu; 1222 pdu->Opcode = IOP_SCSI_Task_Management | OP_IMMEDIATE; 1223 pdu->Flags = FLAG_FINAL | function; 1224 1225 ccb->CmdSN = conn->session->CmdSN; 1226 pdu->p.task_req.CmdSN = htonl(ccb->CmdSN); 1227 1228 if (ref_ccb != NULL) { 1229 pdu->p.task_req.ReferencedTaskTag = ref_ccb->ITT; 1230 pdu->p.task_req.RefCmdSN = htonl(ref_ccb->CmdSN); 1231 pdu->p.task_req.ExpDataSN = htonl(ref_ccb->DataSN_buf.ExpSN); 1232 } else 1233 pdu->p.task_req.ReferencedTaskTag = 0xffffffff; 1234 1235 ppdu->flags |= PDUF_PRIORITY; 1236 1237 setup_tx_uio(ppdu, 0, NULL, FALSE); 1238 send_pdu(ccb, ppdu, (xs) ? CCBDISP_SCSIPI : CCBDISP_WAIT, PDUDISP_FREE); 1239 1240 if (xs == NULL) { 1241 int rc = ccb->status; 1242 free_ccb(ccb); 1243 return rc; 1244 } 1245 return 0; 1246 } 1247 1248 1249 /* 1250 * send_data_out: 1251 * Send data to target in response to an R2T or as unsolicited data. 1252 * 1253 * Parameter: 1254 * conn The connection 1255 * rx_pdu The received R2T PDU (NULL if unsolicited) 1256 * tx_ccb The originally sent command CCB 1257 * waitok Whether it's OK to wait for an available PDU or not 1258 */ 1259 1260 int 1261 send_data_out(connection_t *conn, pdu_t *rx_pdu, ccb_t *tx_ccb, 1262 ccb_disp_t disp, bool waitok) 1263 { 1264 pdu_header_t *pdu; 1265 uint32_t totlen, len, offs, sn; 1266 pdu_t *tx_pdu; 1267 1268 assert(conn->max_transfer != 0); 1269 1270 if (rx_pdu) { 1271 offs = ntohl(rx_pdu->pdu.p.r2t.BufferOffset); 1272 totlen = ntohl(rx_pdu->pdu.p.r2t.DesiredDataTransferLength); 1273 } else { 1274 offs = conn->max_firstimmed; 1275 totlen = min(conn->max_firstdata - offs, tx_ccb->data_len - offs); 1276 } 1277 sn = 0; 1278 1279 while (totlen) { 1280 len = min(totlen, conn->max_transfer); 1281 1282 tx_pdu = get_pdu_c(conn, waitok); 1283 if (tx_pdu == NULL) { 1284 DEBOUT(("No PDU in send_data_out\n")); 1285 1286 tx_ccb->status = ISCSI_STATUS_NO_RESOURCES; 1287 handle_connection_error(conn, ISCSI_STATUS_NO_RESOURCES, NO_LOGOUT); 1288 1289 return ISCSI_STATUS_NO_RESOURCES; 1290 } 1291 1292 totlen -= len; 1293 pdu = &tx_pdu->pdu; 1294 pdu->Opcode = IOP_SCSI_Data_out; 1295 if (!totlen) 1296 pdu->Flags = FLAG_FINAL; 1297 1298 if (rx_pdu != NULL) 1299 pdu->p.data_out.TargetTransferTag = 1300 rx_pdu->pdu.p.r2t.TargetTransferTag; 1301 else 1302 pdu->p.data_out.TargetTransferTag = 0xffffffff; 1303 pdu->p.data_out.BufferOffset = htonl(offs); 1304 pdu->p.data_out.DataSN = htonl(sn); 1305 1306 PERF_PDUSET(tx_pdu, tx_ccb, PERF_BEGIN_PDUWRITEDATA); 1307 1308 DEBC(conn, 10, ("Send DataOut: DataSN %d, len %d offs %x totlen %d\n", 1309 sn, len, offs, totlen)); 1310 1311 setup_tx_uio(tx_pdu, len, tx_ccb->data_ptr + offs, FALSE); 1312 1313 send_pdu(tx_ccb, tx_pdu, (totlen) ? CCBDISP_NOWAIT : disp, PDUDISP_FREE); 1314 1315 sn++; 1316 offs += len; 1317 } 1318 return 0; 1319 } 1320 1321 1322 /* 1323 * send_command: 1324 * Send a SCSI command request. 1325 * 1326 * Parameter: 1327 * CCB The CCB 1328 * disp The CCB disposition 1329 */ 1330 1331 void 1332 send_command(ccb_t *ccb, ccb_disp_t disp, bool waitok, bool immed) 1333 { 1334 uint32_t totlen, len; 1335 connection_t *conn = ccb->connection; 1336 session_t *sess = ccb->session; 1337 pdu_t *ppdu; 1338 pdu_header_t *pdu; 1339 int s; 1340 1341 PERF_BEGIN(ccb, !waitok); 1342 1343 if (!waitok) { 1344 s = splbio(); 1345 if (/*CONSTCOND*/ISCSI_TROTTLING_ENABLED && 1346 /*CONSTCOND*/ISCSI_SERVER_TRUSTED && 1347 !sn_a_le_b(sess->CmdSN, sess->MaxCmdSN)) { 1348 TAILQ_INSERT_TAIL(&sess->ccbs_throttled, ccb, chain); 1349 splx(s); 1350 PDEBOUT(("Throttling S - CmdSN = %d, MaxCmdSN = %d\n", 1351 sess->CmdSN, sess->MaxCmdSN)); 1352 return; 1353 } 1354 splx(s); 1355 ppdu = get_pdu_c(conn, FALSE); 1356 if (ppdu == NULL) { 1357 ccb->status = ISCSI_STATUS_NO_RESOURCES; 1358 iscsi_done(ccb); 1359 return; 1360 } 1361 } else { 1362 s = splbio(); 1363 while (/*CONSTCOND*/ISCSI_TROTTLING_ENABLED && 1364 /*CONSTCOND*/ISCSI_SERVER_TRUSTED && 1365 !sn_a_le_b(sess->CmdSN, sess->MaxCmdSN)) { 1366 ccb->flags |= CCBF_WAITING; 1367 TAILQ_INSERT_TAIL(&sess->ccbs_throttled, ccb, chain); 1368 PDEBOUT(("Throttling W - CmdSN = %d, MaxCmdSN = %d\n", 1369 sess->CmdSN, sess->MaxCmdSN)); 1370 tsleep(ccb, PWAIT, "waitMaxCmd", 0); 1371 splbio(); 1372 } 1373 splx(s); 1374 ppdu = get_pdu(conn); 1375 } 1376 1377 pdu = &ppdu->pdu; 1378 pdu->LUN = htonq(ccb->lun); 1379 memcpy(pdu->p.command.SCSI_CDB, ccb->cmd, ccb->cmdlen); 1380 totlen = len = ccb->data_len; 1381 pdu->Opcode = IOP_SCSI_Command; 1382 if (immed) 1383 pdu->Opcode |= OP_IMMEDIATE; 1384 pdu->p.command.ExpectedDataTransferLength = htonl(totlen); 1385 1386 1387 if (totlen) { 1388 if (ccb->data_in) { 1389 pdu->Flags = FLAG_READ; 1390 totlen = 0; 1391 } else { 1392 pdu->Flags = FLAG_WRITE; 1393 len = min(totlen, conn->max_firstimmed); 1394 /* this means InitialR2T=Yes or FirstBurstLength=0 */ 1395 if (!len) 1396 totlen = 0; 1397 else 1398 totlen -= len; 1399 } 1400 } 1401 1402 if (!totlen) 1403 pdu->Flags |= FLAG_FINAL; 1404 1405 if (ccb->data_in) 1406 init_sernum(&ccb->DataSN_buf); 1407 1408 ccb->sense_len_got = 0; 1409 ccb->xfer_len = 0; 1410 ccb->residual = 0; 1411 ccb->flags |= CCBF_REASSIGN; 1412 1413 s = splbio(); 1414 ccb->CmdSN = sess->CmdSN; 1415 if (!immed) 1416 sess->CmdSN++; 1417 splx(s); 1418 1419 pdu->p.command.CmdSN = htonl(ccb->CmdSN); 1420 1421 DEBC(conn, 10, ("Send Command: CmdSN %d, data_in %d, len %d, totlen %d\n", 1422 ccb->CmdSN, ccb->data_in, len, totlen)); 1423 1424 PERF_PDUSET(ppdu, ccb, PERF_BEGIN_PDUWRITECMD); 1425 1426 setup_tx_uio(ppdu, len, ccb->data_ptr, ccb->data_in); 1427 1428 send_pdu(ccb, ppdu, (totlen) ? CCBDISP_DEFER : disp, PDUDISP_WAIT); 1429 1430 if (totlen) 1431 send_data_out(conn, NULL, ccb, disp, waitok); 1432 } 1433 1434 1435 /* 1436 * send_run_xfer: 1437 * Handle a SCSI command transfer request from scsipi. 1438 * 1439 * Parameter: 1440 * session The session 1441 * xs The transfer parameters 1442 */ 1443 1444 void 1445 send_run_xfer(session_t *session, struct scsipi_xfer *xs) 1446 { 1447 ccb_t *ccb; 1448 connection_t *conn; 1449 bool waitok; 1450 1451 waitok = !(xs->xs_control & XS_CTL_NOSLEEP); 1452 1453 DEB(10, ("RunXfer: flags=%x, data=%p, datalen=%d, resid=%d, cmdlen=%d, " 1454 "waitok=%d\n", xs->xs_control, xs->data, xs->datalen, 1455 xs->resid, xs->cmdlen, waitok)); 1456 1457 conn = assign_connection(session, waitok); 1458 1459 if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE) { 1460 xs->error = XS_REQUEUE; 1461 DEBC(conn, 10, ("run_xfer on dead connection\n")); 1462 scsipi_done(xs); 1463 return; 1464 } 1465 1466 if (xs->xs_control & XS_CTL_RESET) { 1467 if (send_task_management(conn, NULL, xs, TARGET_WARM_RESET)) { 1468 xs->error = XS_SELTIMEOUT; 1469 scsipi_done(xs); 1470 } 1471 return; 1472 } 1473 1474 ccb = get_ccb(conn, waitok); 1475 if (ccb == NULL) { 1476 xs->error = XS_RESOURCE_SHORTAGE; 1477 DEBC(conn, 0, ("No CCB in run_xfer\n")); 1478 scsipi_done(xs); 1479 return; 1480 } 1481 /* copy parameters into CCB for easier access */ 1482 ccb->xs = xs; 1483 1484 ccb->data_in = (xs->xs_control & XS_CTL_DATA_IN) != 0; 1485 ccb->data_len = (uint32_t) xs->datalen; 1486 ccb->data_ptr = xs->data; 1487 1488 ccb->sense_len_req = sizeof(xs->sense.scsi_sense); 1489 ccb->sense_ptr = &xs->sense; 1490 1491 ccb->lun = (uint64_t) xs->xs_periph->periph_lun << 48; 1492 ccb->cmd = (uint8_t *) xs->cmd; 1493 ccb->cmdlen = xs->cmdlen; 1494 DEB(10, ("RunXfer: Periph_lun = %d, cmd[1] = %x, cmdlen = %d\n", 1495 xs->xs_periph->periph_lun, ccb->cmd[1], xs->cmdlen)); 1496 1497 #ifdef LUN_1 1498 ccb->lun += 0x1000000000000LL; 1499 ccb->cmd[1] += 0x10; 1500 #endif 1501 send_command(ccb, CCBDISP_SCSIPI, waitok, FALSE); 1502 } 1503 1504 1505 #ifndef ISCSI_MINIMAL 1506 /* 1507 * send_io_command: 1508 * Handle a SCSI io command request from user space. 1509 * 1510 * Parameter: 1511 * session The session 1512 * lun The LUN to use 1513 * req The SCSI request block 1514 * immed Immediate command if TRUE 1515 * conn_id Assign to this connection ID if nonzero 1516 */ 1517 1518 int 1519 send_io_command(session_t *session, uint64_t lun, scsireq_t *req, 1520 bool immed, uint32_t conn_id) 1521 { 1522 ccb_t *ccb; 1523 connection_t *conn; 1524 int rc; 1525 1526 DEB(9, ("IoCommand: lun=%x, datalen=%d, cmdlen=%d, immed=%d, cid=%d\n", 1527 (int) lun, (int) req->datalen, (int) req->cmdlen, immed, conn_id)); 1528 1529 conn = (conn_id) ? find_connection(session, conn_id) 1530 : assign_connection(session, TRUE); 1531 1532 if (conn == NULL || conn->terminating || conn->state != ST_FULL_FEATURE) { 1533 DEBOUT(("io_command on dead connection (state = %d)\n", 1534 (conn != NULL) ? conn->state : -1)); 1535 return ISCSI_STATUS_INVALID_CONNECTION_ID; 1536 } 1537 1538 ccb = get_ccb(conn, TRUE); 1539 if (ccb == NULL) { 1540 DEBOUT(("No CCB in io_command\n")); 1541 return ISCSI_STATUS_NO_RESOURCES; 1542 } 1543 1544 ccb->data_in = (req->flags & SCCMD_READ) != 0; 1545 ccb->data_len = (uint32_t) req->datalen; 1546 ccb->data_ptr = req->databuf; 1547 1548 ccb->sense_len_req = req->senselen; 1549 ccb->sense_ptr = &req->sense; 1550 1551 ccb->lun = lun; 1552 ccb->cmd = (uint8_t *) req->cmd; 1553 ccb->cmdlen = req->cmdlen; 1554 DEBC(conn, 10, ("IoCommand: cmd[1] = %x, cmdlen = %d\n", 1555 ccb->cmd[1], ccb->cmdlen)); 1556 1557 send_command(ccb, CCBDISP_WAIT, TRUE, immed); 1558 1559 rc = ccb->status; 1560 1561 req->senselen_used = ccb->sense_len_got; 1562 req->datalen_used = req->datalen - ccb->residual; 1563 1564 free_ccb(ccb); 1565 1566 return rc; 1567 } 1568 #endif 1569 1570 1571 /***************************************************************************** 1572 * Timeout handlers 1573 *****************************************************************************/ 1574 /* 1575 * connection_timeout: 1576 * Handle prolonged silence on a connection by checking whether 1577 * it's still alive. 1578 * This has the side effect of discovering missing status or lost commands 1579 * before those time out. 1580 * 1581 * Parameter: 1582 * par The connection 1583 */ 1584 1585 void 1586 connection_timeout(void *par) 1587 { 1588 connection_t *conn = (connection_t *) par; 1589 1590 PDEBC(conn, 1, ("Connection Timeout, num_timeouts=%d\n", 1591 conn->num_timeouts)); 1592 1593 if (++conn->num_timeouts > MAX_CONN_TIMEOUTS) 1594 handle_connection_error(conn, ISCSI_STATUS_TIMEOUT, NO_LOGOUT); 1595 else { 1596 if (conn->state == ST_FULL_FEATURE) 1597 send_nop_out(conn, NULL); 1598 1599 SET_CONN_TIMEOUT(conn, CONNECTION_TIMEOUT); 1600 } 1601 } 1602 1603 /* 1604 * ccb_timeout: 1605 * Handle timeout of a sent command. 1606 * 1607 * Parameter: 1608 * par The CCB 1609 */ 1610 1611 void 1612 ccb_timeout(void *par) 1613 { 1614 ccb_t *ccb = (ccb_t *) par; 1615 connection_t *conn = ccb->connection; 1616 1617 PDEBC(conn, 1, ("CCB Timeout, ccb=%x, num_timeouts=%d\n", 1618 (int) ccb, ccb->num_timeouts)); 1619 1620 /* ignore CCB timeouts outside full feature phase */ 1621 if (conn->state != ST_FULL_FEATURE) 1622 return; 1623 1624 ccb->total_tries++; 1625 1626 if (++ccb->num_timeouts > MAX_CCB_TIMEOUTS || 1627 ccb->total_tries > MAX_CCB_TRIES || 1628 ccb->disp <= CCBDISP_FREE || 1629 !ccb->session->ErrorRecoveryLevel) { 1630 handle_connection_error(conn, ISCSI_STATUS_TIMEOUT, 1631 (ccb->total_tries <= MAX_CCB_TRIES) ? RECOVER_CONNECTION 1632 : LOGOUT_CONNECTION); 1633 } else { 1634 if (ccb->data_in && ccb->xfer_len < ccb->data_len) { 1635 /* request resend of all missing data */ 1636 snack_missing(conn, ccb, SNACK_DATA_NAK, 0, 0); 1637 } else { 1638 /* request resend of all missing status */ 1639 snack_missing(conn, NULL, SNACK_STATUS_NAK, 0, 0); 1640 } 1641 SET_CCB_TIMEOUT(conn, ccb, COMMAND_TIMEOUT); 1642 } 1643 } 1644