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