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