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