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