1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2012 The FreeBSD Foundation 5 * 6 * This software was developed by Edward Tomasz Napierala under sponsorship 7 * from the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 * 30 */ 31 32 #include <sys/cdefs.h> 33 __FBSDID("$FreeBSD$"); 34 35 #include <sys/param.h> 36 #include <sys/condvar.h> 37 #include <sys/conf.h> 38 #include <sys/endian.h> 39 #include <sys/eventhandler.h> 40 #include <sys/file.h> 41 #include <sys/kernel.h> 42 #include <sys/kthread.h> 43 #include <sys/lock.h> 44 #include <sys/malloc.h> 45 #include <sys/mutex.h> 46 #include <sys/module.h> 47 #include <sys/socket.h> 48 #include <sys/sysctl.h> 49 #include <sys/systm.h> 50 #include <sys/sx.h> 51 #include <vm/uma.h> 52 53 #include <cam/cam.h> 54 #include <cam/cam_ccb.h> 55 #include <cam/cam_xpt.h> 56 #include <cam/cam_debug.h> 57 #include <cam/cam_sim.h> 58 #include <cam/cam_xpt_sim.h> 59 #include <cam/cam_xpt_periph.h> 60 #include <cam/cam_periph.h> 61 #include <cam/scsi/scsi_all.h> 62 #include <cam/scsi/scsi_message.h> 63 64 #include <dev/iscsi/icl.h> 65 #include <dev/iscsi/icl_wrappers.h> 66 #include <dev/iscsi/iscsi_ioctl.h> 67 #include <dev/iscsi/iscsi_proto.h> 68 #include <dev/iscsi/iscsi.h> 69 70 #ifdef ICL_KERNEL_PROXY 71 #include <sys/socketvar.h> 72 #endif 73 74 #ifdef ICL_KERNEL_PROXY 75 FEATURE(iscsi_kernel_proxy, "iSCSI initiator built with ICL_KERNEL_PROXY"); 76 #endif 77 78 /* 79 * XXX: This is global so the iscsi_unload() can access it. 80 * Think about how to do this properly. 81 */ 82 static struct iscsi_softc *sc; 83 84 SYSCTL_NODE(_kern, OID_AUTO, iscsi, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 85 "iSCSI initiator"); 86 static int debug = 1; 87 SYSCTL_INT(_kern_iscsi, OID_AUTO, debug, CTLFLAG_RWTUN, 88 &debug, 0, "Enable debug messages"); 89 static int ping_timeout = 5; 90 SYSCTL_INT(_kern_iscsi, OID_AUTO, ping_timeout, CTLFLAG_RWTUN, &ping_timeout, 91 0, "Timeout for ping (NOP-Out) requests, in seconds"); 92 static int iscsid_timeout = 60; 93 SYSCTL_INT(_kern_iscsi, OID_AUTO, iscsid_timeout, CTLFLAG_RWTUN, &iscsid_timeout, 94 0, "Time to wait for iscsid(8) to handle reconnection, in seconds"); 95 static int login_timeout = 60; 96 SYSCTL_INT(_kern_iscsi, OID_AUTO, login_timeout, CTLFLAG_RWTUN, &login_timeout, 97 0, "Time to wait for iscsid(8) to finish Login Phase, in seconds"); 98 static int maxtags = 255; 99 SYSCTL_INT(_kern_iscsi, OID_AUTO, maxtags, CTLFLAG_RWTUN, &maxtags, 100 0, "Max number of IO requests queued"); 101 static int fail_on_disconnection = 0; 102 SYSCTL_INT(_kern_iscsi, OID_AUTO, fail_on_disconnection, CTLFLAG_RWTUN, 103 &fail_on_disconnection, 0, "Destroy CAM SIM on connection failure"); 104 static int fail_on_shutdown = 1; 105 SYSCTL_INT(_kern_iscsi, OID_AUTO, fail_on_shutdown, CTLFLAG_RWTUN, 106 &fail_on_shutdown, 0, "Fail disconnected sessions on shutdown"); 107 108 static MALLOC_DEFINE(M_ISCSI, "iSCSI", "iSCSI initiator"); 109 static uma_zone_t iscsi_outstanding_zone; 110 111 #define CONN_SESSION(X) ((struct iscsi_session *)X->ic_prv0) 112 #define PDU_SESSION(X) (CONN_SESSION(X->ip_conn)) 113 114 #define ISCSI_DEBUG(X, ...) \ 115 do { \ 116 if (debug > 1) \ 117 printf("%s: " X "\n", __func__, ## __VA_ARGS__);\ 118 } while (0) 119 120 #define ISCSI_WARN(X, ...) \ 121 do { \ 122 if (debug > 0) { \ 123 printf("WARNING: %s: " X "\n", \ 124 __func__, ## __VA_ARGS__); \ 125 } \ 126 } while (0) 127 128 #define ISCSI_SESSION_DEBUG(S, X, ...) \ 129 do { \ 130 if (debug > 1) { \ 131 printf("%s: %s (%s): " X "\n", \ 132 __func__, S->is_conf.isc_target_addr, \ 133 S->is_conf.isc_target, ## __VA_ARGS__); \ 134 } \ 135 } while (0) 136 137 #define ISCSI_SESSION_WARN(S, X, ...) \ 138 do { \ 139 if (debug > 0) { \ 140 printf("WARNING: %s (%s): " X "\n", \ 141 S->is_conf.isc_target_addr, \ 142 S->is_conf.isc_target, ## __VA_ARGS__); \ 143 } \ 144 } while (0) 145 146 #define ISCSI_SESSION_LOCK(X) mtx_lock(&X->is_lock) 147 #define ISCSI_SESSION_UNLOCK(X) mtx_unlock(&X->is_lock) 148 #define ISCSI_SESSION_LOCK_ASSERT(X) mtx_assert(&X->is_lock, MA_OWNED) 149 #define ISCSI_SESSION_LOCK_ASSERT_NOT(X) mtx_assert(&X->is_lock, MA_NOTOWNED) 150 151 static int iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, 152 int mode, struct thread *td); 153 154 static struct cdevsw iscsi_cdevsw = { 155 .d_version = D_VERSION, 156 .d_ioctl = iscsi_ioctl, 157 .d_name = "iscsi", 158 }; 159 160 static void iscsi_pdu_queue_locked(struct icl_pdu *request); 161 static void iscsi_pdu_queue(struct icl_pdu *request); 162 static void iscsi_pdu_update_statsn(const struct icl_pdu *response); 163 static void iscsi_pdu_handle_nop_in(struct icl_pdu *response); 164 static void iscsi_pdu_handle_scsi_response(struct icl_pdu *response); 165 static void iscsi_pdu_handle_task_response(struct icl_pdu *response); 166 static void iscsi_pdu_handle_data_in(struct icl_pdu *response); 167 static void iscsi_pdu_handle_logout_response(struct icl_pdu *response); 168 static void iscsi_pdu_handle_r2t(struct icl_pdu *response); 169 static void iscsi_pdu_handle_async_message(struct icl_pdu *response); 170 static void iscsi_pdu_handle_reject(struct icl_pdu *response); 171 static void iscsi_session_reconnect(struct iscsi_session *is); 172 static void iscsi_session_terminate(struct iscsi_session *is); 173 static void iscsi_action(struct cam_sim *sim, union ccb *ccb); 174 static struct iscsi_outstanding *iscsi_outstanding_find(struct iscsi_session *is, 175 uint32_t initiator_task_tag); 176 static struct iscsi_outstanding *iscsi_outstanding_add(struct iscsi_session *is, 177 struct icl_pdu *request, union ccb *ccb, 178 uint32_t *initiator_task_tagp); 179 static void iscsi_outstanding_remove(struct iscsi_session *is, 180 struct iscsi_outstanding *io); 181 182 static bool 183 iscsi_pdu_prepare(struct icl_pdu *request) 184 { 185 struct iscsi_session *is; 186 struct iscsi_bhs_scsi_command *bhssc; 187 188 is = PDU_SESSION(request); 189 190 ISCSI_SESSION_LOCK_ASSERT(is); 191 192 /* 193 * We're only using fields common for all the request 194 * (initiator -> target) PDUs. 195 */ 196 bhssc = (struct iscsi_bhs_scsi_command *)request->ip_bhs; 197 198 /* 199 * Data-Out PDU does not contain CmdSN. 200 */ 201 if (bhssc->bhssc_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_OUT) { 202 if (ISCSI_SNGT(is->is_cmdsn, is->is_maxcmdsn) && 203 (bhssc->bhssc_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0) { 204 /* 205 * Current MaxCmdSN prevents us from sending any more 206 * SCSI Command PDUs to the target; postpone the PDU. 207 * It will get resent by either iscsi_pdu_queue(), 208 * or by maintenance thread. 209 */ 210 #if 0 211 ISCSI_SESSION_DEBUG(is, "postponing send, CmdSN %u, " 212 "ExpCmdSN %u, MaxCmdSN %u, opcode 0x%x", 213 is->is_cmdsn, is->is_expcmdsn, is->is_maxcmdsn, 214 bhssc->bhssc_opcode); 215 #endif 216 return (true); 217 } 218 bhssc->bhssc_cmdsn = htonl(is->is_cmdsn); 219 if ((bhssc->bhssc_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0) 220 is->is_cmdsn++; 221 } 222 bhssc->bhssc_expstatsn = htonl(is->is_statsn + 1); 223 224 return (false); 225 } 226 227 static void 228 iscsi_session_send_postponed(struct iscsi_session *is) 229 { 230 struct icl_pdu *request; 231 bool postpone; 232 233 ISCSI_SESSION_LOCK_ASSERT(is); 234 235 if (STAILQ_EMPTY(&is->is_postponed)) 236 return; 237 while ((request = STAILQ_FIRST(&is->is_postponed)) != NULL) { 238 postpone = iscsi_pdu_prepare(request); 239 if (postpone) 240 return; 241 STAILQ_REMOVE_HEAD(&is->is_postponed, ip_next); 242 icl_pdu_queue(request); 243 } 244 xpt_release_simq(is->is_sim, 1); 245 } 246 247 static void 248 iscsi_pdu_queue_locked(struct icl_pdu *request) 249 { 250 struct iscsi_session *is; 251 bool postpone; 252 253 is = PDU_SESSION(request); 254 ISCSI_SESSION_LOCK_ASSERT(is); 255 iscsi_session_send_postponed(is); 256 postpone = iscsi_pdu_prepare(request); 257 if (postpone) { 258 if (STAILQ_EMPTY(&is->is_postponed)) 259 xpt_freeze_simq(is->is_sim, 1); 260 STAILQ_INSERT_TAIL(&is->is_postponed, request, ip_next); 261 return; 262 } 263 icl_pdu_queue(request); 264 } 265 266 static void 267 iscsi_pdu_queue(struct icl_pdu *request) 268 { 269 struct iscsi_session *is; 270 271 is = PDU_SESSION(request); 272 ISCSI_SESSION_LOCK(is); 273 iscsi_pdu_queue_locked(request); 274 ISCSI_SESSION_UNLOCK(is); 275 } 276 277 static void 278 iscsi_session_logout(struct iscsi_session *is) 279 { 280 struct icl_pdu *request; 281 struct iscsi_bhs_logout_request *bhslr; 282 283 request = icl_pdu_new(is->is_conn, M_NOWAIT); 284 if (request == NULL) 285 return; 286 287 bhslr = (struct iscsi_bhs_logout_request *)request->ip_bhs; 288 bhslr->bhslr_opcode = ISCSI_BHS_OPCODE_LOGOUT_REQUEST; 289 bhslr->bhslr_reason = BHSLR_REASON_CLOSE_SESSION; 290 iscsi_pdu_queue_locked(request); 291 } 292 293 static void 294 iscsi_session_terminate_task(struct iscsi_session *is, 295 struct iscsi_outstanding *io, cam_status status) 296 { 297 298 ISCSI_SESSION_LOCK_ASSERT(is); 299 300 if (io->io_ccb != NULL) { 301 io->io_ccb->ccb_h.status &= ~(CAM_SIM_QUEUED | CAM_STATUS_MASK); 302 io->io_ccb->ccb_h.status |= status; 303 if ((io->io_ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 304 io->io_ccb->ccb_h.status |= CAM_DEV_QFRZN; 305 xpt_freeze_devq(io->io_ccb->ccb_h.path, 1); 306 ISCSI_SESSION_DEBUG(is, "freezing devq"); 307 } 308 xpt_done(io->io_ccb); 309 } 310 iscsi_outstanding_remove(is, io); 311 } 312 313 static void 314 iscsi_session_terminate_tasks(struct iscsi_session *is, cam_status status) 315 { 316 struct iscsi_outstanding *io, *tmp; 317 318 ISCSI_SESSION_LOCK_ASSERT(is); 319 320 TAILQ_FOREACH_SAFE(io, &is->is_outstanding, io_next, tmp) { 321 iscsi_session_terminate_task(is, io, status); 322 } 323 } 324 325 static void 326 iscsi_session_cleanup(struct iscsi_session *is, bool destroy_sim) 327 { 328 struct icl_pdu *pdu; 329 330 ISCSI_SESSION_LOCK_ASSERT(is); 331 332 /* 333 * Don't queue any new PDUs. 334 */ 335 if (is->is_sim != NULL && is->is_simq_frozen == false) { 336 ISCSI_SESSION_DEBUG(is, "freezing"); 337 xpt_freeze_simq(is->is_sim, 1); 338 is->is_simq_frozen = true; 339 } 340 341 /* 342 * Remove postponed PDUs. 343 */ 344 if (!STAILQ_EMPTY(&is->is_postponed)) 345 xpt_release_simq(is->is_sim, 1); 346 while ((pdu = STAILQ_FIRST(&is->is_postponed)) != NULL) { 347 STAILQ_REMOVE_HEAD(&is->is_postponed, ip_next); 348 icl_pdu_free(pdu); 349 } 350 351 if (destroy_sim == false) { 352 /* 353 * Terminate SCSI tasks, asking CAM to requeue them. 354 */ 355 iscsi_session_terminate_tasks(is, CAM_REQUEUE_REQ); 356 return; 357 } 358 359 iscsi_session_terminate_tasks(is, CAM_DEV_NOT_THERE); 360 361 if (is->is_sim == NULL) 362 return; 363 364 ISCSI_SESSION_DEBUG(is, "deregistering SIM"); 365 xpt_async(AC_LOST_DEVICE, is->is_path, NULL); 366 367 if (is->is_simq_frozen) { 368 is->is_simq_frozen = false; 369 xpt_release_simq(is->is_sim, 1); 370 } 371 372 xpt_free_path(is->is_path); 373 is->is_path = NULL; 374 xpt_bus_deregister(cam_sim_path(is->is_sim)); 375 cam_sim_free(is->is_sim, TRUE /*free_devq*/); 376 is->is_sim = NULL; 377 is->is_devq = NULL; 378 } 379 380 static void 381 iscsi_maintenance_thread_reconnect(struct iscsi_session *is) 382 { 383 384 icl_conn_close(is->is_conn); 385 386 ISCSI_SESSION_LOCK(is); 387 388 is->is_connected = false; 389 is->is_reconnecting = false; 390 is->is_login_phase = false; 391 392 #ifdef ICL_KERNEL_PROXY 393 if (is->is_login_pdu != NULL) { 394 icl_pdu_free(is->is_login_pdu); 395 is->is_login_pdu = NULL; 396 } 397 cv_signal(&is->is_login_cv); 398 #endif 399 400 if (fail_on_disconnection) { 401 ISCSI_SESSION_DEBUG(is, "connection failed, destroying devices"); 402 iscsi_session_cleanup(is, true); 403 } else { 404 iscsi_session_cleanup(is, false); 405 } 406 407 KASSERT(TAILQ_EMPTY(&is->is_outstanding), 408 ("destroying session with active tasks")); 409 KASSERT(STAILQ_EMPTY(&is->is_postponed), 410 ("destroying session with postponed PDUs")); 411 412 if (is->is_conf.isc_enable == 0 && is->is_conf.isc_discovery == 0) { 413 ISCSI_SESSION_UNLOCK(is); 414 return; 415 } 416 417 /* 418 * Request immediate reconnection from iscsid(8). 419 */ 420 //ISCSI_SESSION_DEBUG(is, "waking up iscsid(8)"); 421 is->is_waiting_for_iscsid = true; 422 strlcpy(is->is_reason, "Waiting for iscsid(8)", sizeof(is->is_reason)); 423 is->is_timeout = 0; 424 ISCSI_SESSION_UNLOCK(is); 425 cv_signal(&is->is_softc->sc_cv); 426 } 427 428 static void 429 iscsi_maintenance_thread_terminate(struct iscsi_session *is) 430 { 431 struct iscsi_softc *sc; 432 433 sc = is->is_softc; 434 sx_xlock(&sc->sc_lock); 435 TAILQ_REMOVE(&sc->sc_sessions, is, is_next); 436 sx_xunlock(&sc->sc_lock); 437 438 icl_conn_close(is->is_conn); 439 callout_drain(&is->is_callout); 440 441 ISCSI_SESSION_LOCK(is); 442 443 KASSERT(is->is_terminating, ("is_terminating == false")); 444 445 #ifdef ICL_KERNEL_PROXY 446 if (is->is_login_pdu != NULL) { 447 icl_pdu_free(is->is_login_pdu); 448 is->is_login_pdu = NULL; 449 } 450 cv_signal(&is->is_login_cv); 451 #endif 452 453 iscsi_session_cleanup(is, true); 454 455 KASSERT(TAILQ_EMPTY(&is->is_outstanding), 456 ("destroying session with active tasks")); 457 KASSERT(STAILQ_EMPTY(&is->is_postponed), 458 ("destroying session with postponed PDUs")); 459 460 ISCSI_SESSION_UNLOCK(is); 461 462 icl_conn_free(is->is_conn); 463 mtx_destroy(&is->is_lock); 464 cv_destroy(&is->is_maintenance_cv); 465 #ifdef ICL_KERNEL_PROXY 466 cv_destroy(&is->is_login_cv); 467 #endif 468 469 ISCSI_SESSION_DEBUG(is, "terminated"); 470 free(is, M_ISCSI); 471 472 /* 473 * The iscsi_unload() routine might be waiting. 474 */ 475 cv_signal(&sc->sc_cv); 476 } 477 478 static void 479 iscsi_maintenance_thread(void *arg) 480 { 481 struct iscsi_session *is = arg; 482 483 ISCSI_SESSION_LOCK(is); 484 for (;;) { 485 if (is->is_reconnecting == false && 486 is->is_terminating == false && 487 (STAILQ_EMPTY(&is->is_postponed) || 488 ISCSI_SNGT(is->is_cmdsn, is->is_maxcmdsn))) 489 cv_wait(&is->is_maintenance_cv, &is->is_lock); 490 491 /* Terminate supersedes reconnect. */ 492 if (is->is_terminating) { 493 ISCSI_SESSION_UNLOCK(is); 494 iscsi_maintenance_thread_terminate(is); 495 kthread_exit(); 496 return; 497 } 498 499 if (is->is_reconnecting) { 500 ISCSI_SESSION_UNLOCK(is); 501 iscsi_maintenance_thread_reconnect(is); 502 ISCSI_SESSION_LOCK(is); 503 continue; 504 } 505 506 iscsi_session_send_postponed(is); 507 } 508 ISCSI_SESSION_UNLOCK(is); 509 } 510 511 static void 512 iscsi_session_reconnect(struct iscsi_session *is) 513 { 514 515 /* 516 * XXX: We can't use locking here, because 517 * it's being called from various contexts. 518 * Hope it doesn't break anything. 519 */ 520 if (is->is_reconnecting) 521 return; 522 523 is->is_reconnecting = true; 524 cv_signal(&is->is_maintenance_cv); 525 } 526 527 static void 528 iscsi_session_terminate(struct iscsi_session *is) 529 { 530 531 if (is->is_terminating) 532 return; 533 534 is->is_terminating = true; 535 536 #if 0 537 iscsi_session_logout(is); 538 #endif 539 cv_signal(&is->is_maintenance_cv); 540 } 541 542 static void 543 iscsi_callout(void *context) 544 { 545 struct icl_pdu *request; 546 struct iscsi_bhs_nop_out *bhsno; 547 struct iscsi_session *is; 548 bool reconnect_needed = false; 549 sbintime_t sbt, pr; 550 551 is = context; 552 553 ISCSI_SESSION_LOCK(is); 554 if (is->is_terminating) { 555 ISCSI_SESSION_UNLOCK(is); 556 return; 557 } 558 559 sbt = mstosbt(995); 560 pr = mstosbt(10); 561 callout_schedule_sbt(&is->is_callout, sbt, pr, 0); 562 563 if (is->is_conf.isc_enable == 0) 564 goto out; 565 566 is->is_timeout++; 567 568 if (is->is_waiting_for_iscsid) { 569 if (iscsid_timeout > 0 && is->is_timeout > iscsid_timeout) { 570 ISCSI_SESSION_WARN(is, "timed out waiting for iscsid(8) " 571 "for %d seconds; reconnecting", 572 is->is_timeout); 573 reconnect_needed = true; 574 } 575 goto out; 576 } 577 578 if (is->is_login_phase) { 579 if (login_timeout > 0 && is->is_timeout > login_timeout) { 580 ISCSI_SESSION_WARN(is, "login timed out after %d seconds; " 581 "reconnecting", is->is_timeout); 582 reconnect_needed = true; 583 } 584 goto out; 585 } 586 587 if (ping_timeout <= 0) { 588 /* 589 * Pings are disabled. Don't send NOP-Out in this case. 590 * Reset the timeout, to avoid triggering reconnection, 591 * should the user decide to reenable them. 592 */ 593 is->is_timeout = 0; 594 goto out; 595 } 596 597 if (is->is_timeout >= ping_timeout) { 598 ISCSI_SESSION_WARN(is, "no ping reply (NOP-In) after %d seconds; " 599 "reconnecting", ping_timeout); 600 reconnect_needed = true; 601 goto out; 602 } 603 604 ISCSI_SESSION_UNLOCK(is); 605 606 /* 607 * If the ping was reset less than one second ago - which means 608 * that we've received some PDU during the last second - assume 609 * the traffic flows correctly and don't bother sending a NOP-Out. 610 * 611 * (It's 2 - one for one second, and one for incrementing is_timeout 612 * earlier in this routine.) 613 */ 614 if (is->is_timeout < 2) 615 return; 616 617 request = icl_pdu_new(is->is_conn, M_NOWAIT); 618 if (request == NULL) { 619 ISCSI_SESSION_WARN(is, "failed to allocate PDU"); 620 return; 621 } 622 bhsno = (struct iscsi_bhs_nop_out *)request->ip_bhs; 623 bhsno->bhsno_opcode = ISCSI_BHS_OPCODE_NOP_OUT | 624 ISCSI_BHS_OPCODE_IMMEDIATE; 625 bhsno->bhsno_flags = 0x80; 626 bhsno->bhsno_target_transfer_tag = 0xffffffff; 627 iscsi_pdu_queue(request); 628 return; 629 630 out: 631 if (is->is_terminating) { 632 ISCSI_SESSION_UNLOCK(is); 633 return; 634 } 635 636 ISCSI_SESSION_UNLOCK(is); 637 638 if (reconnect_needed) 639 iscsi_session_reconnect(is); 640 } 641 642 static void 643 iscsi_pdu_update_statsn(const struct icl_pdu *response) 644 { 645 const struct iscsi_bhs_data_in *bhsdi; 646 struct iscsi_session *is; 647 uint32_t expcmdsn, maxcmdsn, statsn; 648 649 is = PDU_SESSION(response); 650 651 ISCSI_SESSION_LOCK_ASSERT(is); 652 653 /* 654 * We're only using fields common for all the response 655 * (target -> initiator) PDUs. 656 */ 657 bhsdi = (const struct iscsi_bhs_data_in *)response->ip_bhs; 658 /* 659 * Ok, I lied. In case of Data-In, "The fields StatSN, Status, 660 * and Residual Count only have meaningful content if the S bit 661 * is set to 1", so we also need to check the bit specific for 662 * Data-In PDU. 663 */ 664 if (bhsdi->bhsdi_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_IN || 665 (bhsdi->bhsdi_flags & BHSDI_FLAGS_S) != 0) { 666 statsn = ntohl(bhsdi->bhsdi_statsn); 667 if (statsn != is->is_statsn && statsn != (is->is_statsn + 1)) { 668 /* XXX: This is normal situation for MCS */ 669 ISCSI_SESSION_WARN(is, "PDU 0x%x StatSN %u != " 670 "session ExpStatSN %u (or + 1); reconnecting", 671 bhsdi->bhsdi_opcode, statsn, is->is_statsn); 672 iscsi_session_reconnect(is); 673 } 674 if (ISCSI_SNGT(statsn, is->is_statsn)) 675 is->is_statsn = statsn; 676 } 677 678 expcmdsn = ntohl(bhsdi->bhsdi_expcmdsn); 679 maxcmdsn = ntohl(bhsdi->bhsdi_maxcmdsn); 680 681 if (ISCSI_SNLT(maxcmdsn + 1, expcmdsn)) { 682 ISCSI_SESSION_DEBUG(is, 683 "PDU MaxCmdSN %u + 1 < PDU ExpCmdSN %u; ignoring", 684 maxcmdsn, expcmdsn); 685 } else { 686 if (ISCSI_SNGT(maxcmdsn, is->is_maxcmdsn)) { 687 is->is_maxcmdsn = maxcmdsn; 688 689 /* 690 * Command window increased; kick the maintanance thread 691 * to send out postponed commands. 692 */ 693 if (!STAILQ_EMPTY(&is->is_postponed)) 694 cv_signal(&is->is_maintenance_cv); 695 } else if (ISCSI_SNLT(maxcmdsn, is->is_maxcmdsn)) { 696 /* XXX: This is normal situation for MCS */ 697 ISCSI_SESSION_DEBUG(is, 698 "PDU MaxCmdSN %u < session MaxCmdSN %u; ignoring", 699 maxcmdsn, is->is_maxcmdsn); 700 } 701 702 if (ISCSI_SNGT(expcmdsn, is->is_expcmdsn)) { 703 is->is_expcmdsn = expcmdsn; 704 } else if (ISCSI_SNLT(expcmdsn, is->is_expcmdsn)) { 705 /* XXX: This is normal situation for MCS */ 706 ISCSI_SESSION_DEBUG(is, 707 "PDU ExpCmdSN %u < session ExpCmdSN %u; ignoring", 708 expcmdsn, is->is_expcmdsn); 709 } 710 } 711 712 /* 713 * Every incoming PDU - not just NOP-In - resets the ping timer. 714 * The purpose of the timeout is to reset the connection when it stalls; 715 * we don't want this to happen when NOP-In or NOP-Out ends up delayed 716 * in some queue. 717 */ 718 is->is_timeout = 0; 719 } 720 721 static void 722 iscsi_receive_callback(struct icl_pdu *response) 723 { 724 struct iscsi_session *is; 725 726 is = PDU_SESSION(response); 727 728 ISCSI_SESSION_LOCK(is); 729 730 iscsi_pdu_update_statsn(response); 731 732 #ifdef ICL_KERNEL_PROXY 733 if (is->is_login_phase) { 734 if (is->is_login_pdu == NULL) 735 is->is_login_pdu = response; 736 else 737 icl_pdu_free(response); 738 ISCSI_SESSION_UNLOCK(is); 739 cv_signal(&is->is_login_cv); 740 return; 741 } 742 #endif 743 744 /* 745 * The handling routine is responsible for freeing the PDU 746 * when it's no longer needed. 747 */ 748 switch (response->ip_bhs->bhs_opcode) { 749 case ISCSI_BHS_OPCODE_NOP_IN: 750 iscsi_pdu_handle_nop_in(response); 751 ISCSI_SESSION_UNLOCK(is); 752 break; 753 case ISCSI_BHS_OPCODE_SCSI_RESPONSE: 754 iscsi_pdu_handle_scsi_response(response); 755 /* Session lock dropped inside. */ 756 ISCSI_SESSION_LOCK_ASSERT_NOT(is); 757 break; 758 case ISCSI_BHS_OPCODE_TASK_RESPONSE: 759 iscsi_pdu_handle_task_response(response); 760 ISCSI_SESSION_UNLOCK(is); 761 break; 762 case ISCSI_BHS_OPCODE_SCSI_DATA_IN: 763 iscsi_pdu_handle_data_in(response); 764 /* Session lock dropped inside. */ 765 ISCSI_SESSION_LOCK_ASSERT_NOT(is); 766 break; 767 case ISCSI_BHS_OPCODE_LOGOUT_RESPONSE: 768 iscsi_pdu_handle_logout_response(response); 769 ISCSI_SESSION_UNLOCK(is); 770 break; 771 case ISCSI_BHS_OPCODE_R2T: 772 iscsi_pdu_handle_r2t(response); 773 ISCSI_SESSION_UNLOCK(is); 774 break; 775 case ISCSI_BHS_OPCODE_ASYNC_MESSAGE: 776 iscsi_pdu_handle_async_message(response); 777 ISCSI_SESSION_UNLOCK(is); 778 break; 779 case ISCSI_BHS_OPCODE_REJECT: 780 iscsi_pdu_handle_reject(response); 781 ISCSI_SESSION_UNLOCK(is); 782 break; 783 default: 784 ISCSI_SESSION_WARN(is, "received PDU with unsupported " 785 "opcode 0x%x; reconnecting", 786 response->ip_bhs->bhs_opcode); 787 iscsi_session_reconnect(is); 788 ISCSI_SESSION_UNLOCK(is); 789 icl_pdu_free(response); 790 } 791 } 792 793 static void 794 iscsi_error_callback(struct icl_conn *ic) 795 { 796 struct iscsi_session *is; 797 798 is = CONN_SESSION(ic); 799 800 ISCSI_SESSION_WARN(is, "connection error; reconnecting"); 801 iscsi_session_reconnect(is); 802 } 803 804 static void 805 iscsi_pdu_handle_nop_in(struct icl_pdu *response) 806 { 807 struct iscsi_session *is; 808 struct iscsi_bhs_nop_out *bhsno; 809 struct iscsi_bhs_nop_in *bhsni; 810 struct icl_pdu *request; 811 void *data = NULL; 812 size_t datasize; 813 int error; 814 815 is = PDU_SESSION(response); 816 bhsni = (struct iscsi_bhs_nop_in *)response->ip_bhs; 817 818 if (bhsni->bhsni_target_transfer_tag == 0xffffffff) { 819 /* 820 * Nothing to do; iscsi_pdu_update_statsn() already 821 * zeroed the timeout. 822 */ 823 icl_pdu_free(response); 824 return; 825 } 826 827 datasize = icl_pdu_data_segment_length(response); 828 if (datasize > 0) { 829 data = malloc(datasize, M_ISCSI, M_NOWAIT | M_ZERO); 830 if (data == NULL) { 831 ISCSI_SESSION_WARN(is, "failed to allocate memory; " 832 "reconnecting"); 833 icl_pdu_free(response); 834 iscsi_session_reconnect(is); 835 return; 836 } 837 icl_pdu_get_data(response, 0, data, datasize); 838 } 839 840 request = icl_pdu_new(response->ip_conn, M_NOWAIT); 841 if (request == NULL) { 842 ISCSI_SESSION_WARN(is, "failed to allocate memory; " 843 "reconnecting"); 844 free(data, M_ISCSI); 845 icl_pdu_free(response); 846 iscsi_session_reconnect(is); 847 return; 848 } 849 bhsno = (struct iscsi_bhs_nop_out *)request->ip_bhs; 850 bhsno->bhsno_opcode = ISCSI_BHS_OPCODE_NOP_OUT | 851 ISCSI_BHS_OPCODE_IMMEDIATE; 852 bhsno->bhsno_flags = 0x80; 853 bhsno->bhsno_initiator_task_tag = 0xffffffff; 854 bhsno->bhsno_target_transfer_tag = bhsni->bhsni_target_transfer_tag; 855 if (datasize > 0) { 856 error = icl_pdu_append_data(request, data, datasize, M_NOWAIT); 857 if (error != 0) { 858 ISCSI_SESSION_WARN(is, "failed to allocate memory; " 859 "reconnecting"); 860 free(data, M_ISCSI); 861 icl_pdu_free(request); 862 icl_pdu_free(response); 863 iscsi_session_reconnect(is); 864 return; 865 } 866 free(data, M_ISCSI); 867 } 868 869 icl_pdu_free(response); 870 iscsi_pdu_queue_locked(request); 871 } 872 873 static void 874 iscsi_pdu_handle_scsi_response(struct icl_pdu *response) 875 { 876 struct iscsi_bhs_scsi_response *bhssr; 877 struct iscsi_outstanding *io; 878 struct iscsi_session *is; 879 union ccb *ccb; 880 struct ccb_scsiio *csio; 881 size_t data_segment_len, received; 882 uint16_t sense_len; 883 uint32_t resid; 884 885 is = PDU_SESSION(response); 886 887 bhssr = (struct iscsi_bhs_scsi_response *)response->ip_bhs; 888 io = iscsi_outstanding_find(is, bhssr->bhssr_initiator_task_tag); 889 if (io == NULL || io->io_ccb == NULL) { 890 ISCSI_SESSION_WARN(is, "bad itt 0x%x", bhssr->bhssr_initiator_task_tag); 891 icl_pdu_free(response); 892 iscsi_session_reconnect(is); 893 ISCSI_SESSION_UNLOCK(is); 894 return; 895 } 896 897 ccb = io->io_ccb; 898 if (bhssr->bhssr_response == BHSSR_RESPONSE_COMMAND_COMPLETED) { 899 if (ntohl(bhssr->bhssr_expdatasn) != io->io_datasn) { 900 ISCSI_SESSION_WARN(is, 901 "ExpDataSN mismatch in SCSI Response (%u vs %u)", 902 ntohl(bhssr->bhssr_expdatasn), io->io_datasn); 903 904 /* 905 * XXX: Permit an ExpDataSN of zero for errors. 906 * 907 * This doesn't conform to RFC 7143, but some 908 * targets seem to do this. 909 */ 910 if (bhssr->bhssr_status != 0 && 911 bhssr->bhssr_expdatasn == htonl(0)) 912 goto skip_expdatasn; 913 914 icl_pdu_free(response); 915 iscsi_session_reconnect(is); 916 ISCSI_SESSION_UNLOCK(is); 917 return; 918 } 919 } else { 920 if (bhssr->bhssr_expdatasn != htonl(0)) { 921 ISCSI_SESSION_WARN(is, 922 "ExpDataSN mismatch in SCSI Response (%u vs 0)", 923 ntohl(bhssr->bhssr_expdatasn)); 924 icl_pdu_free(response); 925 iscsi_session_reconnect(is); 926 ISCSI_SESSION_UNLOCK(is); 927 return; 928 } 929 } 930 skip_expdatasn: 931 932 /* 933 * With iSER, after getting good response we can be sure 934 * that all the data has been successfully transferred. 935 */ 936 if (is->is_conn->ic_iser) { 937 resid = ntohl(bhssr->bhssr_residual_count); 938 if (bhssr->bhssr_flags & BHSSR_FLAGS_RESIDUAL_UNDERFLOW) { 939 io->io_received = ccb->csio.dxfer_len - resid; 940 } else if (bhssr->bhssr_flags & BHSSR_FLAGS_RESIDUAL_OVERFLOW) { 941 ISCSI_SESSION_WARN(is, "overflow: target indicates %d", resid); 942 } else { 943 io->io_received = ccb->csio.dxfer_len; 944 } 945 } 946 947 received = io->io_received; 948 iscsi_outstanding_remove(is, io); 949 ISCSI_SESSION_UNLOCK(is); 950 951 if (bhssr->bhssr_response != BHSSR_RESPONSE_COMMAND_COMPLETED) { 952 ISCSI_SESSION_WARN(is, "service response 0x%x", bhssr->bhssr_response); 953 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 954 xpt_freeze_devq(ccb->ccb_h.path, 1); 955 ISCSI_SESSION_DEBUG(is, "freezing devq"); 956 } 957 ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN; 958 } else if (bhssr->bhssr_status == 0) { 959 ccb->ccb_h.status = CAM_REQ_CMP; 960 } else { 961 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 962 xpt_freeze_devq(ccb->ccb_h.path, 1); 963 ISCSI_SESSION_DEBUG(is, "freezing devq"); 964 } 965 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_DEV_QFRZN; 966 ccb->csio.scsi_status = bhssr->bhssr_status; 967 } 968 969 csio = &ccb->csio; 970 data_segment_len = icl_pdu_data_segment_length(response); 971 if (data_segment_len > 0) { 972 if (data_segment_len < sizeof(sense_len)) { 973 ISCSI_SESSION_WARN(is, "truncated data segment (%zd bytes)", 974 data_segment_len); 975 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 976 xpt_freeze_devq(ccb->ccb_h.path, 1); 977 ISCSI_SESSION_DEBUG(is, "freezing devq"); 978 } 979 ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN; 980 goto out; 981 } 982 icl_pdu_get_data(response, 0, &sense_len, sizeof(sense_len)); 983 sense_len = ntohs(sense_len); 984 #if 0 985 ISCSI_SESSION_DEBUG(is, "sense_len %d, data len %zd", 986 sense_len, data_segment_len); 987 #endif 988 if (sizeof(sense_len) + sense_len > data_segment_len) { 989 ISCSI_SESSION_WARN(is, "truncated data segment " 990 "(%zd bytes, should be %zd)", 991 data_segment_len, sizeof(sense_len) + sense_len); 992 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 993 xpt_freeze_devq(ccb->ccb_h.path, 1); 994 ISCSI_SESSION_DEBUG(is, "freezing devq"); 995 } 996 ccb->ccb_h.status = CAM_REQ_CMP_ERR | CAM_DEV_QFRZN; 997 goto out; 998 } else if (sizeof(sense_len) + sense_len < data_segment_len) 999 ISCSI_SESSION_WARN(is, "oversize data segment " 1000 "(%zd bytes, should be %zd)", 1001 data_segment_len, sizeof(sense_len) + sense_len); 1002 if (sense_len > csio->sense_len) { 1003 ISCSI_SESSION_DEBUG(is, "truncating sense from %d to %d", 1004 sense_len, csio->sense_len); 1005 sense_len = csio->sense_len; 1006 } 1007 icl_pdu_get_data(response, sizeof(sense_len), &csio->sense_data, sense_len); 1008 csio->sense_resid = csio->sense_len - sense_len; 1009 ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 1010 } 1011 1012 out: 1013 if (bhssr->bhssr_flags & BHSSR_FLAGS_RESIDUAL_UNDERFLOW) 1014 csio->resid = ntohl(bhssr->bhssr_residual_count); 1015 1016 if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1017 KASSERT(received <= csio->dxfer_len, 1018 ("received > csio->dxfer_len")); 1019 if (received < csio->dxfer_len) { 1020 if (csio->resid != csio->dxfer_len - received) { 1021 ISCSI_SESSION_WARN(is, "underflow mismatch: " 1022 "target indicates %d, we calculated %zd", 1023 csio->resid, csio->dxfer_len - received); 1024 } 1025 csio->resid = csio->dxfer_len - received; 1026 } 1027 } 1028 1029 xpt_done(ccb); 1030 icl_pdu_free(response); 1031 } 1032 1033 static void 1034 iscsi_pdu_handle_task_response(struct icl_pdu *response) 1035 { 1036 struct iscsi_bhs_task_management_response *bhstmr; 1037 struct iscsi_outstanding *io, *aio; 1038 struct iscsi_session *is; 1039 1040 is = PDU_SESSION(response); 1041 1042 bhstmr = (struct iscsi_bhs_task_management_response *)response->ip_bhs; 1043 io = iscsi_outstanding_find(is, bhstmr->bhstmr_initiator_task_tag); 1044 if (io == NULL || io->io_ccb != NULL) { 1045 ISCSI_SESSION_WARN(is, "bad itt 0x%x", 1046 bhstmr->bhstmr_initiator_task_tag); 1047 icl_pdu_free(response); 1048 iscsi_session_reconnect(is); 1049 return; 1050 } 1051 1052 if (bhstmr->bhstmr_response != BHSTMR_RESPONSE_FUNCTION_COMPLETE) { 1053 ISCSI_SESSION_WARN(is, "task response 0x%x", 1054 bhstmr->bhstmr_response); 1055 } else { 1056 aio = iscsi_outstanding_find(is, io->io_referenced_task_tag); 1057 if (aio != NULL && aio->io_ccb != NULL) 1058 iscsi_session_terminate_task(is, aio, CAM_REQ_ABORTED); 1059 } 1060 1061 iscsi_outstanding_remove(is, io); 1062 icl_pdu_free(response); 1063 } 1064 1065 static void 1066 iscsi_pdu_handle_data_in(struct icl_pdu *response) 1067 { 1068 struct iscsi_bhs_data_in *bhsdi; 1069 struct iscsi_outstanding *io; 1070 struct iscsi_session *is; 1071 union ccb *ccb; 1072 struct ccb_scsiio *csio; 1073 size_t data_segment_len, received, oreceived; 1074 1075 is = PDU_SESSION(response); 1076 bhsdi = (struct iscsi_bhs_data_in *)response->ip_bhs; 1077 io = iscsi_outstanding_find(is, bhsdi->bhsdi_initiator_task_tag); 1078 if (io == NULL || io->io_ccb == NULL) { 1079 ISCSI_SESSION_WARN(is, "bad itt 0x%x", bhsdi->bhsdi_initiator_task_tag); 1080 icl_pdu_free(response); 1081 iscsi_session_reconnect(is); 1082 ISCSI_SESSION_UNLOCK(is); 1083 return; 1084 } 1085 1086 if (io->io_datasn != ntohl(bhsdi->bhsdi_datasn)) { 1087 ISCSI_SESSION_WARN(is, "received Data-In PDU with " 1088 "DataSN %u, while expected %u; dropping connection", 1089 ntohl(bhsdi->bhsdi_datasn), io->io_datasn); 1090 icl_pdu_free(response); 1091 iscsi_session_reconnect(is); 1092 ISCSI_SESSION_UNLOCK(is); 1093 return; 1094 } 1095 io->io_datasn += response->ip_additional_pdus + 1; 1096 1097 data_segment_len = icl_pdu_data_segment_length(response); 1098 if (data_segment_len == 0) { 1099 /* 1100 * "The sending of 0 length data segments should be avoided, 1101 * but initiators and targets MUST be able to properly receive 1102 * 0 length data segments." 1103 */ 1104 ISCSI_SESSION_UNLOCK(is); 1105 icl_pdu_free(response); 1106 return; 1107 } 1108 1109 /* 1110 * We need to track this for security reasons - without it, malicious target 1111 * could respond to SCSI READ without sending Data-In PDUs, which would result 1112 * in read operation on the initiator side returning random kernel data. 1113 */ 1114 if (ntohl(bhsdi->bhsdi_buffer_offset) != io->io_received) { 1115 ISCSI_SESSION_WARN(is, "data out of order; expected offset %zd, got %zd", 1116 io->io_received, (size_t)ntohl(bhsdi->bhsdi_buffer_offset)); 1117 icl_pdu_free(response); 1118 iscsi_session_reconnect(is); 1119 ISCSI_SESSION_UNLOCK(is); 1120 return; 1121 } 1122 1123 ccb = io->io_ccb; 1124 csio = &ccb->csio; 1125 1126 if (io->io_received + data_segment_len > csio->dxfer_len) { 1127 ISCSI_SESSION_WARN(is, "oversize data segment (%zd bytes " 1128 "at offset %zd, buffer is %d)", 1129 data_segment_len, io->io_received, csio->dxfer_len); 1130 icl_pdu_free(response); 1131 iscsi_session_reconnect(is); 1132 ISCSI_SESSION_UNLOCK(is); 1133 return; 1134 } 1135 1136 oreceived = io->io_received; 1137 io->io_received += data_segment_len; 1138 received = io->io_received; 1139 if ((bhsdi->bhsdi_flags & BHSDI_FLAGS_S) != 0) 1140 iscsi_outstanding_remove(is, io); 1141 ISCSI_SESSION_UNLOCK(is); 1142 1143 icl_pdu_get_data(response, 0, csio->data_ptr + oreceived, data_segment_len); 1144 1145 /* 1146 * XXX: Check F. 1147 */ 1148 if ((bhsdi->bhsdi_flags & BHSDI_FLAGS_S) == 0) { 1149 /* 1150 * Nothing more to do. 1151 */ 1152 icl_pdu_free(response); 1153 return; 1154 } 1155 1156 //ISCSI_SESSION_DEBUG(is, "got S flag; status 0x%x", bhsdi->bhsdi_status); 1157 if (bhsdi->bhsdi_status == 0) { 1158 ccb->ccb_h.status = CAM_REQ_CMP; 1159 } else { 1160 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 1161 xpt_freeze_devq(ccb->ccb_h.path, 1); 1162 ISCSI_SESSION_DEBUG(is, "freezing devq"); 1163 } 1164 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_DEV_QFRZN; 1165 csio->scsi_status = bhsdi->bhsdi_status; 1166 } 1167 1168 if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 1169 KASSERT(received <= csio->dxfer_len, 1170 ("received > csio->dxfer_len")); 1171 if (received < csio->dxfer_len) { 1172 csio->resid = ntohl(bhsdi->bhsdi_residual_count); 1173 if (csio->resid != csio->dxfer_len - received) { 1174 ISCSI_SESSION_WARN(is, "underflow mismatch: " 1175 "target indicates %d, we calculated %zd", 1176 csio->resid, csio->dxfer_len - received); 1177 } 1178 csio->resid = csio->dxfer_len - received; 1179 } 1180 } 1181 1182 xpt_done(ccb); 1183 icl_pdu_free(response); 1184 } 1185 1186 static void 1187 iscsi_pdu_handle_logout_response(struct icl_pdu *response) 1188 { 1189 1190 ISCSI_SESSION_DEBUG(PDU_SESSION(response), "logout response"); 1191 icl_pdu_free(response); 1192 } 1193 1194 static void 1195 iscsi_pdu_handle_r2t(struct icl_pdu *response) 1196 { 1197 struct icl_pdu *request; 1198 struct iscsi_session *is; 1199 struct iscsi_bhs_r2t *bhsr2t; 1200 struct iscsi_bhs_data_out *bhsdo; 1201 struct iscsi_outstanding *io; 1202 struct ccb_scsiio *csio; 1203 size_t off, len, max_send_data_segment_length, total_len; 1204 int error; 1205 uint32_t datasn = 0; 1206 1207 is = PDU_SESSION(response); 1208 1209 bhsr2t = (struct iscsi_bhs_r2t *)response->ip_bhs; 1210 io = iscsi_outstanding_find(is, bhsr2t->bhsr2t_initiator_task_tag); 1211 if (io == NULL || io->io_ccb == NULL) { 1212 ISCSI_SESSION_WARN(is, "bad itt 0x%x; reconnecting", 1213 bhsr2t->bhsr2t_initiator_task_tag); 1214 icl_pdu_free(response); 1215 iscsi_session_reconnect(is); 1216 return; 1217 } 1218 1219 csio = &io->io_ccb->csio; 1220 1221 if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_OUT) { 1222 ISCSI_SESSION_WARN(is, "received R2T for read command; reconnecting"); 1223 icl_pdu_free(response); 1224 iscsi_session_reconnect(is); 1225 return; 1226 } 1227 1228 /* 1229 * XXX: Verify R2TSN. 1230 */ 1231 1232 off = ntohl(bhsr2t->bhsr2t_buffer_offset); 1233 if (off > csio->dxfer_len) { 1234 ISCSI_SESSION_WARN(is, "target requested invalid offset " 1235 "%zd, buffer is is %d; reconnecting", off, csio->dxfer_len); 1236 icl_pdu_free(response); 1237 iscsi_session_reconnect(is); 1238 return; 1239 } 1240 1241 total_len = ntohl(bhsr2t->bhsr2t_desired_data_transfer_length); 1242 if (total_len == 0 || total_len > csio->dxfer_len) { 1243 ISCSI_SESSION_WARN(is, "target requested invalid length " 1244 "%zd, buffer is %d; reconnecting", total_len, csio->dxfer_len); 1245 icl_pdu_free(response); 1246 iscsi_session_reconnect(is); 1247 return; 1248 } 1249 1250 //ISCSI_SESSION_DEBUG(is, "r2t; off %zd, len %zd", off, total_len); 1251 1252 if (is->is_conn->ic_hw_isomax != 0) 1253 max_send_data_segment_length = is->is_conn->ic_hw_isomax; 1254 else 1255 max_send_data_segment_length = 1256 is->is_conn->ic_max_send_data_segment_length; 1257 for (;;) { 1258 len = total_len; 1259 1260 if (len > max_send_data_segment_length) 1261 len = max_send_data_segment_length; 1262 1263 if (off + len > csio->dxfer_len) { 1264 ISCSI_SESSION_WARN(is, "target requested invalid " 1265 "length/offset %zd, buffer is %d; reconnecting", 1266 off + len, csio->dxfer_len); 1267 icl_pdu_free(response); 1268 iscsi_session_reconnect(is); 1269 return; 1270 } 1271 1272 request = icl_pdu_new(response->ip_conn, M_NOWAIT); 1273 if (request == NULL) { 1274 icl_pdu_free(response); 1275 iscsi_session_reconnect(is); 1276 return; 1277 } 1278 1279 bhsdo = (struct iscsi_bhs_data_out *)request->ip_bhs; 1280 bhsdo->bhsdo_opcode = ISCSI_BHS_OPCODE_SCSI_DATA_OUT; 1281 bhsdo->bhsdo_lun = bhsr2t->bhsr2t_lun; 1282 bhsdo->bhsdo_initiator_task_tag = 1283 bhsr2t->bhsr2t_initiator_task_tag; 1284 bhsdo->bhsdo_target_transfer_tag = 1285 bhsr2t->bhsr2t_target_transfer_tag; 1286 bhsdo->bhsdo_datasn = htonl(datasn); 1287 bhsdo->bhsdo_buffer_offset = htonl(off); 1288 error = icl_pdu_append_data(request, csio->data_ptr + off, len, 1289 M_NOWAIT); 1290 if (error != 0) { 1291 ISCSI_SESSION_WARN(is, "failed to allocate memory; " 1292 "reconnecting"); 1293 icl_pdu_free(request); 1294 icl_pdu_free(response); 1295 iscsi_session_reconnect(is); 1296 return; 1297 } 1298 1299 datasn += howmany(len, 1300 is->is_conn->ic_max_send_data_segment_length); 1301 off += len; 1302 total_len -= len; 1303 1304 if (total_len == 0) { 1305 bhsdo->bhsdo_flags |= BHSDO_FLAGS_F; 1306 //ISCSI_SESSION_DEBUG(is, "setting F, off %zd", off); 1307 } else { 1308 //ISCSI_SESSION_DEBUG(is, "not finished, off %zd", off); 1309 } 1310 1311 iscsi_pdu_queue_locked(request); 1312 1313 if (total_len == 0) 1314 break; 1315 } 1316 1317 icl_pdu_free(response); 1318 } 1319 1320 static void 1321 iscsi_pdu_handle_async_message(struct icl_pdu *response) 1322 { 1323 struct iscsi_bhs_asynchronous_message *bhsam; 1324 struct iscsi_session *is; 1325 1326 is = PDU_SESSION(response); 1327 bhsam = (struct iscsi_bhs_asynchronous_message *)response->ip_bhs; 1328 switch (bhsam->bhsam_async_event) { 1329 case BHSAM_EVENT_TARGET_REQUESTS_LOGOUT: 1330 ISCSI_SESSION_WARN(is, "target requests logout; removing session"); 1331 iscsi_session_logout(is); 1332 iscsi_session_terminate(is); 1333 break; 1334 case BHSAM_EVENT_TARGET_TERMINATES_CONNECTION: 1335 ISCSI_SESSION_WARN(is, "target indicates it will drop the connection"); 1336 break; 1337 case BHSAM_EVENT_TARGET_TERMINATES_SESSION: 1338 ISCSI_SESSION_WARN(is, "target indicates it will drop the session"); 1339 break; 1340 default: 1341 /* 1342 * XXX: Technically, we're obligated to also handle 1343 * parameter renegotiation. 1344 */ 1345 ISCSI_SESSION_WARN(is, "ignoring AsyncEvent %d", bhsam->bhsam_async_event); 1346 break; 1347 } 1348 1349 icl_pdu_free(response); 1350 } 1351 1352 static void 1353 iscsi_pdu_handle_reject(struct icl_pdu *response) 1354 { 1355 struct iscsi_bhs_reject *bhsr; 1356 struct iscsi_session *is; 1357 1358 is = PDU_SESSION(response); 1359 bhsr = (struct iscsi_bhs_reject *)response->ip_bhs; 1360 ISCSI_SESSION_WARN(is, "received Reject PDU, reason 0x%x; protocol error?", 1361 bhsr->bhsr_reason); 1362 1363 icl_pdu_free(response); 1364 } 1365 1366 static int 1367 iscsi_ioctl_daemon_wait(struct iscsi_softc *sc, 1368 struct iscsi_daemon_request *request) 1369 { 1370 struct iscsi_session *is; 1371 struct icl_drv_limits idl; 1372 int error; 1373 1374 sx_slock(&sc->sc_lock); 1375 for (;;) { 1376 TAILQ_FOREACH(is, &sc->sc_sessions, is_next) { 1377 ISCSI_SESSION_LOCK(is); 1378 if (is->is_conf.isc_enable == 0 && 1379 is->is_conf.isc_discovery == 0) { 1380 ISCSI_SESSION_UNLOCK(is); 1381 continue; 1382 } 1383 if (is->is_waiting_for_iscsid) 1384 break; 1385 ISCSI_SESSION_UNLOCK(is); 1386 } 1387 1388 if (is == NULL) { 1389 if (sc->sc_unloading) { 1390 sx_sunlock(&sc->sc_lock); 1391 return (ENXIO); 1392 } 1393 1394 /* 1395 * No session requires attention from iscsid(8); wait. 1396 */ 1397 error = cv_wait_sig(&sc->sc_cv, &sc->sc_lock); 1398 if (error != 0) { 1399 sx_sunlock(&sc->sc_lock); 1400 return (error); 1401 } 1402 continue; 1403 } 1404 1405 is->is_waiting_for_iscsid = false; 1406 is->is_login_phase = true; 1407 is->is_reason[0] = '\0'; 1408 ISCSI_SESSION_UNLOCK(is); 1409 1410 request->idr_session_id = is->is_id; 1411 memcpy(&request->idr_isid, &is->is_isid, 1412 sizeof(request->idr_isid)); 1413 request->idr_tsih = 0; /* New or reinstated session. */ 1414 memcpy(&request->idr_conf, &is->is_conf, 1415 sizeof(request->idr_conf)); 1416 1417 error = icl_limits(is->is_conf.isc_offload, 1418 is->is_conf.isc_iser, &idl); 1419 if (error != 0) { 1420 ISCSI_SESSION_WARN(is, "icl_limits for offload \"%s\" " 1421 "failed with error %d", is->is_conf.isc_offload, 1422 error); 1423 sx_sunlock(&sc->sc_lock); 1424 return (error); 1425 } 1426 request->idr_limits.isl_max_recv_data_segment_length = 1427 idl.idl_max_recv_data_segment_length; 1428 request->idr_limits.isl_max_send_data_segment_length = 1429 idl.idl_max_send_data_segment_length; 1430 request->idr_limits.isl_max_burst_length = 1431 idl.idl_max_burst_length; 1432 request->idr_limits.isl_first_burst_length = 1433 idl.idl_first_burst_length; 1434 1435 sx_sunlock(&sc->sc_lock); 1436 return (0); 1437 } 1438 } 1439 1440 static int 1441 iscsi_ioctl_daemon_handoff(struct iscsi_softc *sc, 1442 struct iscsi_daemon_handoff *handoff) 1443 { 1444 struct iscsi_session *is; 1445 struct icl_conn *ic; 1446 int error; 1447 1448 sx_slock(&sc->sc_lock); 1449 1450 /* 1451 * Find the session to hand off socket to. 1452 */ 1453 TAILQ_FOREACH(is, &sc->sc_sessions, is_next) { 1454 if (is->is_id == handoff->idh_session_id) 1455 break; 1456 } 1457 if (is == NULL) { 1458 sx_sunlock(&sc->sc_lock); 1459 return (ESRCH); 1460 } 1461 ISCSI_SESSION_LOCK(is); 1462 ic = is->is_conn; 1463 if (is->is_conf.isc_discovery || is->is_terminating) { 1464 ISCSI_SESSION_UNLOCK(is); 1465 sx_sunlock(&sc->sc_lock); 1466 return (EINVAL); 1467 } 1468 if (is->is_connected) { 1469 /* 1470 * This might have happened because another iscsid(8) 1471 * instance handed off the connection in the meantime. 1472 * Just return. 1473 */ 1474 ISCSI_SESSION_WARN(is, "handoff on already connected " 1475 "session"); 1476 ISCSI_SESSION_UNLOCK(is); 1477 sx_sunlock(&sc->sc_lock); 1478 return (EBUSY); 1479 } 1480 1481 strlcpy(is->is_target_alias, handoff->idh_target_alias, 1482 sizeof(is->is_target_alias)); 1483 is->is_tsih = handoff->idh_tsih; 1484 is->is_statsn = handoff->idh_statsn; 1485 is->is_protocol_level = handoff->idh_protocol_level; 1486 is->is_initial_r2t = handoff->idh_initial_r2t; 1487 is->is_immediate_data = handoff->idh_immediate_data; 1488 1489 ic->ic_max_recv_data_segment_length = 1490 handoff->idh_max_recv_data_segment_length; 1491 ic->ic_max_send_data_segment_length = 1492 handoff->idh_max_send_data_segment_length; 1493 is->is_max_burst_length = handoff->idh_max_burst_length; 1494 is->is_first_burst_length = handoff->idh_first_burst_length; 1495 1496 if (handoff->idh_header_digest == ISCSI_DIGEST_CRC32C) 1497 ic->ic_header_crc32c = true; 1498 else 1499 ic->ic_header_crc32c = false; 1500 if (handoff->idh_data_digest == ISCSI_DIGEST_CRC32C) 1501 ic->ic_data_crc32c = true; 1502 else 1503 ic->ic_data_crc32c = false; 1504 ic->ic_maxtags = maxtags; 1505 1506 is->is_cmdsn = 0; 1507 is->is_expcmdsn = 0; 1508 is->is_maxcmdsn = 0; 1509 is->is_waiting_for_iscsid = false; 1510 is->is_login_phase = false; 1511 is->is_timeout = 0; 1512 is->is_connected = true; 1513 is->is_reason[0] = '\0'; 1514 1515 ISCSI_SESSION_UNLOCK(is); 1516 1517 /* 1518 * If we're going through the proxy, the idh_socket will be 0, 1519 * and the ICL module can simply ignore this call. It can also 1520 * use it to determine it's no longer in the Login phase. 1521 */ 1522 error = icl_conn_handoff(ic, handoff->idh_socket); 1523 if (error != 0) { 1524 sx_sunlock(&sc->sc_lock); 1525 iscsi_session_terminate(is); 1526 return (error); 1527 } 1528 1529 sx_sunlock(&sc->sc_lock); 1530 1531 if (is->is_sim != NULL) { 1532 /* 1533 * When reconnecting, there already is SIM allocated for the session. 1534 */ 1535 KASSERT(is->is_simq_frozen, ("reconnect without frozen simq")); 1536 ISCSI_SESSION_LOCK(is); 1537 ISCSI_SESSION_DEBUG(is, "releasing"); 1538 is->is_simq_frozen = false; 1539 xpt_release_simq(is->is_sim, 1); 1540 ISCSI_SESSION_UNLOCK(is); 1541 1542 } else { 1543 ISCSI_SESSION_LOCK(is); 1544 is->is_devq = cam_simq_alloc(ic->ic_maxtags); 1545 if (is->is_devq == NULL) { 1546 ISCSI_SESSION_UNLOCK(is); 1547 ISCSI_SESSION_WARN(is, "failed to allocate simq"); 1548 iscsi_session_terminate(is); 1549 return (ENOMEM); 1550 } 1551 1552 is->is_sim = cam_sim_alloc(iscsi_action, NULL, "iscsi", 1553 is, is->is_id /* unit */, &is->is_lock, 1554 1, ic->ic_maxtags, is->is_devq); 1555 if (is->is_sim == NULL) { 1556 ISCSI_SESSION_UNLOCK(is); 1557 ISCSI_SESSION_WARN(is, "failed to allocate SIM"); 1558 cam_simq_free(is->is_devq); 1559 iscsi_session_terminate(is); 1560 return (ENOMEM); 1561 } 1562 1563 if (xpt_bus_register(is->is_sim, NULL, 0) != 0) { 1564 ISCSI_SESSION_UNLOCK(is); 1565 ISCSI_SESSION_WARN(is, "failed to register bus"); 1566 iscsi_session_terminate(is); 1567 return (ENOMEM); 1568 } 1569 1570 error = xpt_create_path(&is->is_path, /*periph*/NULL, 1571 cam_sim_path(is->is_sim), CAM_TARGET_WILDCARD, 1572 CAM_LUN_WILDCARD); 1573 if (error != CAM_REQ_CMP) { 1574 ISCSI_SESSION_UNLOCK(is); 1575 ISCSI_SESSION_WARN(is, "failed to create path"); 1576 iscsi_session_terminate(is); 1577 return (ENOMEM); 1578 } 1579 ISCSI_SESSION_UNLOCK(is); 1580 } 1581 1582 return (0); 1583 } 1584 1585 static int 1586 iscsi_ioctl_daemon_fail(struct iscsi_softc *sc, 1587 struct iscsi_daemon_fail *fail) 1588 { 1589 struct iscsi_session *is; 1590 1591 sx_slock(&sc->sc_lock); 1592 1593 TAILQ_FOREACH(is, &sc->sc_sessions, is_next) { 1594 if (is->is_id == fail->idf_session_id) 1595 break; 1596 } 1597 if (is == NULL) { 1598 sx_sunlock(&sc->sc_lock); 1599 return (ESRCH); 1600 } 1601 ISCSI_SESSION_LOCK(is); 1602 ISCSI_SESSION_DEBUG(is, "iscsid(8) failed: %s", 1603 fail->idf_reason); 1604 strlcpy(is->is_reason, fail->idf_reason, sizeof(is->is_reason)); 1605 //is->is_waiting_for_iscsid = false; 1606 //is->is_login_phase = true; 1607 //iscsi_session_reconnect(is); 1608 ISCSI_SESSION_UNLOCK(is); 1609 sx_sunlock(&sc->sc_lock); 1610 1611 return (0); 1612 } 1613 1614 #ifdef ICL_KERNEL_PROXY 1615 static int 1616 iscsi_ioctl_daemon_connect(struct iscsi_softc *sc, 1617 struct iscsi_daemon_connect *idc) 1618 { 1619 struct iscsi_session *is; 1620 struct sockaddr *from_sa, *to_sa; 1621 int error; 1622 1623 sx_slock(&sc->sc_lock); 1624 TAILQ_FOREACH(is, &sc->sc_sessions, is_next) { 1625 if (is->is_id == idc->idc_session_id) 1626 break; 1627 } 1628 if (is == NULL) { 1629 sx_sunlock(&sc->sc_lock); 1630 return (ESRCH); 1631 } 1632 sx_sunlock(&sc->sc_lock); 1633 1634 if (idc->idc_from_addrlen > 0) { 1635 error = getsockaddr(&from_sa, (void *)idc->idc_from_addr, idc->idc_from_addrlen); 1636 if (error != 0) { 1637 ISCSI_SESSION_WARN(is, 1638 "getsockaddr failed with error %d", error); 1639 return (error); 1640 } 1641 } else { 1642 from_sa = NULL; 1643 } 1644 error = getsockaddr(&to_sa, (void *)idc->idc_to_addr, idc->idc_to_addrlen); 1645 if (error != 0) { 1646 ISCSI_SESSION_WARN(is, "getsockaddr failed with error %d", 1647 error); 1648 free(from_sa, M_SONAME); 1649 return (error); 1650 } 1651 1652 ISCSI_SESSION_LOCK(is); 1653 is->is_statsn = 0; 1654 is->is_cmdsn = 0; 1655 is->is_expcmdsn = 0; 1656 is->is_maxcmdsn = 0; 1657 is->is_waiting_for_iscsid = false; 1658 is->is_login_phase = true; 1659 is->is_timeout = 0; 1660 ISCSI_SESSION_UNLOCK(is); 1661 1662 error = icl_conn_connect(is->is_conn, idc->idc_domain, 1663 idc->idc_socktype, idc->idc_protocol, from_sa, to_sa); 1664 free(from_sa, M_SONAME); 1665 free(to_sa, M_SONAME); 1666 1667 /* 1668 * Digests are always disabled during login phase. 1669 */ 1670 is->is_conn->ic_header_crc32c = false; 1671 is->is_conn->ic_data_crc32c = false; 1672 1673 return (error); 1674 } 1675 1676 static int 1677 iscsi_ioctl_daemon_send(struct iscsi_softc *sc, 1678 struct iscsi_daemon_send *ids) 1679 { 1680 struct iscsi_session *is; 1681 struct icl_pdu *ip; 1682 size_t datalen; 1683 void *data; 1684 int error; 1685 1686 sx_slock(&sc->sc_lock); 1687 TAILQ_FOREACH(is, &sc->sc_sessions, is_next) { 1688 if (is->is_id == ids->ids_session_id) 1689 break; 1690 } 1691 if (is == NULL) { 1692 sx_sunlock(&sc->sc_lock); 1693 return (ESRCH); 1694 } 1695 sx_sunlock(&sc->sc_lock); 1696 1697 if (is->is_login_phase == false) 1698 return (EBUSY); 1699 1700 if (is->is_terminating || is->is_reconnecting) 1701 return (EIO); 1702 1703 datalen = ids->ids_data_segment_len; 1704 if (datalen > is->is_conn->ic_max_send_data_segment_length) 1705 return (EINVAL); 1706 if (datalen > 0) { 1707 data = malloc(datalen, M_ISCSI, M_WAITOK); 1708 error = copyin(ids->ids_data_segment, data, datalen); 1709 if (error != 0) { 1710 free(data, M_ISCSI); 1711 return (error); 1712 } 1713 } 1714 1715 ip = icl_pdu_new(is->is_conn, M_WAITOK); 1716 memcpy(ip->ip_bhs, ids->ids_bhs, sizeof(*ip->ip_bhs)); 1717 if (datalen > 0) { 1718 error = icl_pdu_append_data(ip, data, datalen, M_WAITOK); 1719 KASSERT(error == 0, ("icl_pdu_append_data(..., M_WAITOK) failed")); 1720 free(data, M_ISCSI); 1721 } 1722 iscsi_pdu_queue(ip); 1723 1724 return (0); 1725 } 1726 1727 static int 1728 iscsi_ioctl_daemon_receive(struct iscsi_softc *sc, 1729 struct iscsi_daemon_receive *idr) 1730 { 1731 struct iscsi_session *is; 1732 struct icl_pdu *ip; 1733 void *data; 1734 int error; 1735 1736 sx_slock(&sc->sc_lock); 1737 TAILQ_FOREACH(is, &sc->sc_sessions, is_next) { 1738 if (is->is_id == idr->idr_session_id) 1739 break; 1740 } 1741 if (is == NULL) { 1742 sx_sunlock(&sc->sc_lock); 1743 return (ESRCH); 1744 } 1745 sx_sunlock(&sc->sc_lock); 1746 1747 if (is->is_login_phase == false) 1748 return (EBUSY); 1749 1750 ISCSI_SESSION_LOCK(is); 1751 while (is->is_login_pdu == NULL && 1752 is->is_terminating == false && 1753 is->is_reconnecting == false) { 1754 error = cv_wait_sig(&is->is_login_cv, &is->is_lock); 1755 if (error != 0) { 1756 ISCSI_SESSION_UNLOCK(is); 1757 return (error); 1758 } 1759 } 1760 if (is->is_terminating || is->is_reconnecting) { 1761 ISCSI_SESSION_UNLOCK(is); 1762 return (EIO); 1763 } 1764 ip = is->is_login_pdu; 1765 is->is_login_pdu = NULL; 1766 ISCSI_SESSION_UNLOCK(is); 1767 1768 if (ip->ip_data_len > idr->idr_data_segment_len) { 1769 icl_pdu_free(ip); 1770 return (EMSGSIZE); 1771 } 1772 1773 copyout(ip->ip_bhs, idr->idr_bhs, sizeof(*ip->ip_bhs)); 1774 if (ip->ip_data_len > 0) { 1775 data = malloc(ip->ip_data_len, M_ISCSI, M_WAITOK); 1776 icl_pdu_get_data(ip, 0, data, ip->ip_data_len); 1777 copyout(data, idr->idr_data_segment, ip->ip_data_len); 1778 free(data, M_ISCSI); 1779 } 1780 1781 icl_pdu_free(ip); 1782 1783 return (0); 1784 } 1785 #endif /* ICL_KERNEL_PROXY */ 1786 1787 static void 1788 iscsi_sanitize_session_conf(struct iscsi_session_conf *isc) 1789 { 1790 /* 1791 * Just make sure all the fields are null-terminated. 1792 * 1793 * XXX: This is not particularly secure. We should 1794 * create our own conf and then copy in relevant 1795 * fields. 1796 */ 1797 isc->isc_initiator[ISCSI_NAME_LEN - 1] = '\0'; 1798 isc->isc_initiator_addr[ISCSI_ADDR_LEN - 1] = '\0'; 1799 isc->isc_initiator_alias[ISCSI_ALIAS_LEN - 1] = '\0'; 1800 isc->isc_target[ISCSI_NAME_LEN - 1] = '\0'; 1801 isc->isc_target_addr[ISCSI_ADDR_LEN - 1] = '\0'; 1802 isc->isc_user[ISCSI_NAME_LEN - 1] = '\0'; 1803 isc->isc_secret[ISCSI_SECRET_LEN - 1] = '\0'; 1804 isc->isc_mutual_user[ISCSI_NAME_LEN - 1] = '\0'; 1805 isc->isc_mutual_secret[ISCSI_SECRET_LEN - 1] = '\0'; 1806 } 1807 1808 static bool 1809 iscsi_valid_session_conf(const struct iscsi_session_conf *isc) 1810 { 1811 1812 if (isc->isc_initiator[0] == '\0') { 1813 ISCSI_DEBUG("empty isc_initiator"); 1814 return (false); 1815 } 1816 1817 if (isc->isc_target_addr[0] == '\0') { 1818 ISCSI_DEBUG("empty isc_target_addr"); 1819 return (false); 1820 } 1821 1822 if (isc->isc_discovery != 0 && isc->isc_target[0] != 0) { 1823 ISCSI_DEBUG("non-empty isc_target for discovery session"); 1824 return (false); 1825 } 1826 1827 if (isc->isc_discovery == 0 && isc->isc_target[0] == 0) { 1828 ISCSI_DEBUG("empty isc_target for non-discovery session"); 1829 return (false); 1830 } 1831 1832 return (true); 1833 } 1834 1835 static int 1836 iscsi_ioctl_session_add(struct iscsi_softc *sc, struct iscsi_session_add *isa) 1837 { 1838 struct iscsi_session *is; 1839 const struct iscsi_session *is2; 1840 int error; 1841 sbintime_t sbt, pr; 1842 1843 iscsi_sanitize_session_conf(&isa->isa_conf); 1844 if (iscsi_valid_session_conf(&isa->isa_conf) == false) 1845 return (EINVAL); 1846 1847 is = malloc(sizeof(*is), M_ISCSI, M_ZERO | M_WAITOK); 1848 memcpy(&is->is_conf, &isa->isa_conf, sizeof(is->is_conf)); 1849 1850 sx_xlock(&sc->sc_lock); 1851 1852 /* 1853 * Prevent duplicates. 1854 */ 1855 TAILQ_FOREACH(is2, &sc->sc_sessions, is_next) { 1856 if (!!is->is_conf.isc_discovery != 1857 !!is2->is_conf.isc_discovery) 1858 continue; 1859 1860 if (strcmp(is->is_conf.isc_target_addr, 1861 is2->is_conf.isc_target_addr) != 0) 1862 continue; 1863 1864 if (is->is_conf.isc_discovery == 0 && 1865 strcmp(is->is_conf.isc_target, 1866 is2->is_conf.isc_target) != 0) 1867 continue; 1868 1869 sx_xunlock(&sc->sc_lock); 1870 free(is, M_ISCSI); 1871 return (EBUSY); 1872 } 1873 1874 is->is_conn = icl_new_conn(is->is_conf.isc_offload, 1875 is->is_conf.isc_iser, "iscsi", &is->is_lock); 1876 if (is->is_conn == NULL) { 1877 sx_xunlock(&sc->sc_lock); 1878 free(is, M_ISCSI); 1879 return (EINVAL); 1880 } 1881 is->is_conn->ic_receive = iscsi_receive_callback; 1882 is->is_conn->ic_error = iscsi_error_callback; 1883 is->is_conn->ic_prv0 = is; 1884 TAILQ_INIT(&is->is_outstanding); 1885 STAILQ_INIT(&is->is_postponed); 1886 mtx_init(&is->is_lock, "iscsi_lock", NULL, MTX_DEF); 1887 cv_init(&is->is_maintenance_cv, "iscsi_mt"); 1888 #ifdef ICL_KERNEL_PROXY 1889 cv_init(&is->is_login_cv, "iscsi_login"); 1890 #endif 1891 1892 /* 1893 * Set some default values, from RFC 3720, section 12. 1894 * 1895 * These values are updated by the handoff IOCTL, but are 1896 * needed prior to the handoff to support sending the ISER 1897 * login PDU. 1898 */ 1899 is->is_conn->ic_max_recv_data_segment_length = 8192; 1900 is->is_conn->ic_max_send_data_segment_length = 8192; 1901 is->is_max_burst_length = 262144; 1902 is->is_first_burst_length = 65536; 1903 1904 is->is_softc = sc; 1905 sc->sc_last_session_id++; 1906 is->is_id = sc->sc_last_session_id; 1907 is->is_isid[0] = 0x80; /* RFC 3720, 10.12.5: 10b, "Random" ISID. */ 1908 arc4rand(&is->is_isid[1], 5, 0); 1909 is->is_tsih = 0; 1910 callout_init(&is->is_callout, 1); 1911 1912 error = kthread_add(iscsi_maintenance_thread, is, NULL, NULL, 0, 0, "iscsimt"); 1913 if (error != 0) { 1914 ISCSI_SESSION_WARN(is, "kthread_add(9) failed with error %d", error); 1915 sx_xunlock(&sc->sc_lock); 1916 return (error); 1917 } 1918 1919 sbt = mstosbt(995); 1920 pr = mstosbt(10); 1921 callout_reset_sbt(&is->is_callout, sbt, pr, iscsi_callout, is, 0); 1922 TAILQ_INSERT_TAIL(&sc->sc_sessions, is, is_next); 1923 1924 ISCSI_SESSION_LOCK(is); 1925 /* 1926 * Don't notify iscsid(8) if the session is disabled and it's not 1927 * a discovery session, 1928 */ 1929 if (is->is_conf.isc_enable == 0 && is->is_conf.isc_discovery == 0) { 1930 ISCSI_SESSION_UNLOCK(is); 1931 sx_xunlock(&sc->sc_lock); 1932 return (0); 1933 } 1934 1935 is->is_waiting_for_iscsid = true; 1936 strlcpy(is->is_reason, "Waiting for iscsid(8)", sizeof(is->is_reason)); 1937 ISCSI_SESSION_UNLOCK(is); 1938 cv_signal(&sc->sc_cv); 1939 sx_xunlock(&sc->sc_lock); 1940 return (0); 1941 } 1942 1943 static bool 1944 iscsi_session_conf_matches(unsigned int id1, const struct iscsi_session_conf *c1, 1945 unsigned int id2, const struct iscsi_session_conf *c2) 1946 { 1947 1948 if (id2 != 0 && id2 != id1) 1949 return (false); 1950 if (c2->isc_target[0] != '\0' && 1951 strcmp(c1->isc_target, c2->isc_target) != 0) 1952 return (false); 1953 if (c2->isc_target_addr[0] != '\0' && 1954 strcmp(c1->isc_target_addr, c2->isc_target_addr) != 0) 1955 return (false); 1956 return (true); 1957 } 1958 1959 static int 1960 iscsi_ioctl_session_remove(struct iscsi_softc *sc, 1961 struct iscsi_session_remove *isr) 1962 { 1963 struct iscsi_session *is, *tmp; 1964 bool found = false; 1965 1966 iscsi_sanitize_session_conf(&isr->isr_conf); 1967 1968 sx_xlock(&sc->sc_lock); 1969 TAILQ_FOREACH_SAFE(is, &sc->sc_sessions, is_next, tmp) { 1970 ISCSI_SESSION_LOCK(is); 1971 if (iscsi_session_conf_matches(is->is_id, &is->is_conf, 1972 isr->isr_session_id, &isr->isr_conf)) { 1973 found = true; 1974 iscsi_session_logout(is); 1975 iscsi_session_terminate(is); 1976 } 1977 ISCSI_SESSION_UNLOCK(is); 1978 } 1979 sx_xunlock(&sc->sc_lock); 1980 1981 if (!found) 1982 return (ESRCH); 1983 1984 return (0); 1985 } 1986 1987 static int 1988 iscsi_ioctl_session_list(struct iscsi_softc *sc, struct iscsi_session_list *isl) 1989 { 1990 int error; 1991 unsigned int i = 0; 1992 struct iscsi_session *is; 1993 struct iscsi_session_state iss; 1994 1995 sx_slock(&sc->sc_lock); 1996 TAILQ_FOREACH(is, &sc->sc_sessions, is_next) { 1997 if (i >= isl->isl_nentries) { 1998 sx_sunlock(&sc->sc_lock); 1999 return (EMSGSIZE); 2000 } 2001 memset(&iss, 0, sizeof(iss)); 2002 memcpy(&iss.iss_conf, &is->is_conf, sizeof(iss.iss_conf)); 2003 iss.iss_id = is->is_id; 2004 strlcpy(iss.iss_target_alias, is->is_target_alias, sizeof(iss.iss_target_alias)); 2005 strlcpy(iss.iss_reason, is->is_reason, sizeof(iss.iss_reason)); 2006 strlcpy(iss.iss_offload, is->is_conn->ic_offload, sizeof(iss.iss_offload)); 2007 2008 if (is->is_conn->ic_header_crc32c) 2009 iss.iss_header_digest = ISCSI_DIGEST_CRC32C; 2010 else 2011 iss.iss_header_digest = ISCSI_DIGEST_NONE; 2012 2013 if (is->is_conn->ic_data_crc32c) 2014 iss.iss_data_digest = ISCSI_DIGEST_CRC32C; 2015 else 2016 iss.iss_data_digest = ISCSI_DIGEST_NONE; 2017 2018 iss.iss_max_send_data_segment_length = 2019 is->is_conn->ic_max_send_data_segment_length; 2020 iss.iss_max_recv_data_segment_length = 2021 is->is_conn->ic_max_recv_data_segment_length; 2022 iss.iss_max_burst_length = is->is_max_burst_length; 2023 iss.iss_first_burst_length = is->is_first_burst_length; 2024 iss.iss_immediate_data = is->is_immediate_data; 2025 iss.iss_connected = is->is_connected; 2026 2027 error = copyout(&iss, isl->isl_pstates + i, sizeof(iss)); 2028 if (error != 0) { 2029 sx_sunlock(&sc->sc_lock); 2030 return (error); 2031 } 2032 i++; 2033 } 2034 sx_sunlock(&sc->sc_lock); 2035 2036 isl->isl_nentries = i; 2037 2038 return (0); 2039 } 2040 2041 static int 2042 iscsi_ioctl_session_modify(struct iscsi_softc *sc, 2043 struct iscsi_session_modify *ism) 2044 { 2045 struct iscsi_session *is; 2046 const struct iscsi_session *is2; 2047 2048 iscsi_sanitize_session_conf(&ism->ism_conf); 2049 if (iscsi_valid_session_conf(&ism->ism_conf) == false) 2050 return (EINVAL); 2051 2052 sx_xlock(&sc->sc_lock); 2053 TAILQ_FOREACH(is, &sc->sc_sessions, is_next) { 2054 ISCSI_SESSION_LOCK(is); 2055 if (is->is_id == ism->ism_session_id) { 2056 /* Note that the session remains locked. */ 2057 break; 2058 } 2059 ISCSI_SESSION_UNLOCK(is); 2060 } 2061 if (is == NULL) { 2062 sx_xunlock(&sc->sc_lock); 2063 return (ESRCH); 2064 } 2065 2066 /* 2067 * Prevent duplicates. 2068 */ 2069 TAILQ_FOREACH(is2, &sc->sc_sessions, is_next) { 2070 if (is == is2) 2071 continue; 2072 2073 if (!!ism->ism_conf.isc_discovery != 2074 !!is2->is_conf.isc_discovery) 2075 continue; 2076 2077 if (strcmp(ism->ism_conf.isc_target_addr, 2078 is2->is_conf.isc_target_addr) != 0) 2079 continue; 2080 2081 if (ism->ism_conf.isc_discovery == 0 && 2082 strcmp(ism->ism_conf.isc_target, 2083 is2->is_conf.isc_target) != 0) 2084 continue; 2085 2086 ISCSI_SESSION_UNLOCK(is); 2087 sx_xunlock(&sc->sc_lock); 2088 return (EBUSY); 2089 } 2090 2091 sx_xunlock(&sc->sc_lock); 2092 2093 memcpy(&is->is_conf, &ism->ism_conf, sizeof(is->is_conf)); 2094 ISCSI_SESSION_UNLOCK(is); 2095 2096 iscsi_session_reconnect(is); 2097 2098 return (0); 2099 } 2100 2101 static int 2102 iscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int mode, 2103 struct thread *td) 2104 { 2105 struct iscsi_softc *sc; 2106 2107 sc = dev->si_drv1; 2108 2109 switch (cmd) { 2110 case ISCSIDWAIT: 2111 return (iscsi_ioctl_daemon_wait(sc, 2112 (struct iscsi_daemon_request *)arg)); 2113 case ISCSIDHANDOFF: 2114 return (iscsi_ioctl_daemon_handoff(sc, 2115 (struct iscsi_daemon_handoff *)arg)); 2116 case ISCSIDFAIL: 2117 return (iscsi_ioctl_daemon_fail(sc, 2118 (struct iscsi_daemon_fail *)arg)); 2119 #ifdef ICL_KERNEL_PROXY 2120 case ISCSIDCONNECT: 2121 return (iscsi_ioctl_daemon_connect(sc, 2122 (struct iscsi_daemon_connect *)arg)); 2123 case ISCSIDSEND: 2124 return (iscsi_ioctl_daemon_send(sc, 2125 (struct iscsi_daemon_send *)arg)); 2126 case ISCSIDRECEIVE: 2127 return (iscsi_ioctl_daemon_receive(sc, 2128 (struct iscsi_daemon_receive *)arg)); 2129 #endif /* ICL_KERNEL_PROXY */ 2130 case ISCSISADD: 2131 return (iscsi_ioctl_session_add(sc, 2132 (struct iscsi_session_add *)arg)); 2133 case ISCSISREMOVE: 2134 return (iscsi_ioctl_session_remove(sc, 2135 (struct iscsi_session_remove *)arg)); 2136 case ISCSISLIST: 2137 return (iscsi_ioctl_session_list(sc, 2138 (struct iscsi_session_list *)arg)); 2139 case ISCSISMODIFY: 2140 return (iscsi_ioctl_session_modify(sc, 2141 (struct iscsi_session_modify *)arg)); 2142 default: 2143 return (EINVAL); 2144 } 2145 } 2146 2147 static struct iscsi_outstanding * 2148 iscsi_outstanding_find(struct iscsi_session *is, uint32_t initiator_task_tag) 2149 { 2150 struct iscsi_outstanding *io; 2151 2152 ISCSI_SESSION_LOCK_ASSERT(is); 2153 2154 TAILQ_FOREACH(io, &is->is_outstanding, io_next) { 2155 if (io->io_initiator_task_tag == initiator_task_tag) 2156 return (io); 2157 } 2158 return (NULL); 2159 } 2160 2161 static struct iscsi_outstanding * 2162 iscsi_outstanding_find_ccb(struct iscsi_session *is, union ccb *ccb) 2163 { 2164 struct iscsi_outstanding *io; 2165 2166 ISCSI_SESSION_LOCK_ASSERT(is); 2167 2168 TAILQ_FOREACH(io, &is->is_outstanding, io_next) { 2169 if (io->io_ccb == ccb) 2170 return (io); 2171 } 2172 return (NULL); 2173 } 2174 2175 static struct iscsi_outstanding * 2176 iscsi_outstanding_add(struct iscsi_session *is, struct icl_pdu *request, 2177 union ccb *ccb, uint32_t *initiator_task_tagp) 2178 { 2179 struct iscsi_outstanding *io; 2180 int error; 2181 2182 ISCSI_SESSION_LOCK_ASSERT(is); 2183 2184 io = uma_zalloc(iscsi_outstanding_zone, M_NOWAIT | M_ZERO); 2185 if (io == NULL) { 2186 ISCSI_SESSION_WARN(is, "failed to allocate %zd bytes", 2187 sizeof(*io)); 2188 return (NULL); 2189 } 2190 2191 error = icl_conn_task_setup(is->is_conn, request, &ccb->csio, 2192 initiator_task_tagp, &io->io_icl_prv); 2193 if (error != 0) { 2194 ISCSI_SESSION_WARN(is, 2195 "icl_conn_task_setup() failed with error %d", error); 2196 uma_zfree(iscsi_outstanding_zone, io); 2197 return (NULL); 2198 } 2199 2200 KASSERT(iscsi_outstanding_find(is, *initiator_task_tagp) == NULL, 2201 ("initiator_task_tag 0x%x already added", *initiator_task_tagp)); 2202 2203 io->io_initiator_task_tag = *initiator_task_tagp; 2204 io->io_ccb = ccb; 2205 TAILQ_INSERT_TAIL(&is->is_outstanding, io, io_next); 2206 return (io); 2207 } 2208 2209 static void 2210 iscsi_outstanding_remove(struct iscsi_session *is, struct iscsi_outstanding *io) 2211 { 2212 2213 ISCSI_SESSION_LOCK_ASSERT(is); 2214 2215 icl_conn_task_done(is->is_conn, io->io_icl_prv); 2216 TAILQ_REMOVE(&is->is_outstanding, io, io_next); 2217 uma_zfree(iscsi_outstanding_zone, io); 2218 } 2219 2220 static void 2221 iscsi_action_abort(struct iscsi_session *is, union ccb *ccb) 2222 { 2223 struct icl_pdu *request; 2224 struct iscsi_bhs_task_management_request *bhstmr; 2225 struct ccb_abort *cab = &ccb->cab; 2226 struct iscsi_outstanding *io, *aio; 2227 uint32_t initiator_task_tag; 2228 2229 ISCSI_SESSION_LOCK_ASSERT(is); 2230 2231 #if 0 2232 KASSERT(is->is_login_phase == false, ("%s called during Login Phase", __func__)); 2233 #else 2234 if (is->is_login_phase) { 2235 ccb->ccb_h.status = CAM_REQ_ABORTED; 2236 xpt_done(ccb); 2237 return; 2238 } 2239 #endif 2240 2241 aio = iscsi_outstanding_find_ccb(is, cab->abort_ccb); 2242 if (aio == NULL) { 2243 ccb->ccb_h.status = CAM_REQ_CMP; 2244 xpt_done(ccb); 2245 return; 2246 } 2247 2248 request = icl_pdu_new(is->is_conn, M_NOWAIT); 2249 if (request == NULL) { 2250 ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 2251 xpt_done(ccb); 2252 return; 2253 } 2254 2255 initiator_task_tag = is->is_initiator_task_tag++; 2256 if (initiator_task_tag == 0xffffffff) 2257 initiator_task_tag = is->is_initiator_task_tag++; 2258 2259 io = iscsi_outstanding_add(is, request, NULL, &initiator_task_tag); 2260 if (io == NULL) { 2261 icl_pdu_free(request); 2262 ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 2263 xpt_done(ccb); 2264 return; 2265 } 2266 io->io_referenced_task_tag = aio->io_initiator_task_tag; 2267 2268 bhstmr = (struct iscsi_bhs_task_management_request *)request->ip_bhs; 2269 bhstmr->bhstmr_opcode = ISCSI_BHS_OPCODE_TASK_REQUEST; 2270 bhstmr->bhstmr_function = 0x80 | BHSTMR_FUNCTION_ABORT_TASK; 2271 bhstmr->bhstmr_lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun)); 2272 bhstmr->bhstmr_initiator_task_tag = initiator_task_tag; 2273 bhstmr->bhstmr_referenced_task_tag = aio->io_initiator_task_tag; 2274 2275 iscsi_pdu_queue_locked(request); 2276 } 2277 2278 static void 2279 iscsi_action_scsiio(struct iscsi_session *is, union ccb *ccb) 2280 { 2281 struct icl_pdu *request; 2282 struct iscsi_bhs_scsi_command *bhssc; 2283 struct ccb_scsiio *csio; 2284 struct iscsi_outstanding *io; 2285 size_t len; 2286 uint32_t initiator_task_tag; 2287 int error; 2288 2289 ISCSI_SESSION_LOCK_ASSERT(is); 2290 2291 #if 0 2292 KASSERT(is->is_login_phase == false, ("%s called during Login Phase", __func__)); 2293 #else 2294 if (is->is_login_phase) { 2295 ISCSI_SESSION_DEBUG(is, "called during login phase"); 2296 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 2297 xpt_freeze_devq(ccb->ccb_h.path, 1); 2298 ISCSI_SESSION_DEBUG(is, "freezing devq"); 2299 } 2300 ccb->ccb_h.status = CAM_REQ_ABORTED | CAM_DEV_QFRZN; 2301 xpt_done(ccb); 2302 return; 2303 } 2304 #endif 2305 2306 request = icl_pdu_new(is->is_conn, M_NOWAIT); 2307 if (request == NULL) { 2308 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 2309 xpt_freeze_devq(ccb->ccb_h.path, 1); 2310 ISCSI_SESSION_DEBUG(is, "freezing devq"); 2311 } 2312 ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN; 2313 xpt_done(ccb); 2314 return; 2315 } 2316 2317 initiator_task_tag = is->is_initiator_task_tag++; 2318 if (initiator_task_tag == 0xffffffff) 2319 initiator_task_tag = is->is_initiator_task_tag++; 2320 2321 io = iscsi_outstanding_add(is, request, ccb, &initiator_task_tag); 2322 if (io == NULL) { 2323 icl_pdu_free(request); 2324 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 2325 xpt_freeze_devq(ccb->ccb_h.path, 1); 2326 ISCSI_SESSION_DEBUG(is, "freezing devq"); 2327 } 2328 ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN; 2329 xpt_done(ccb); 2330 return; 2331 } 2332 2333 csio = &ccb->csio; 2334 bhssc = (struct iscsi_bhs_scsi_command *)request->ip_bhs; 2335 bhssc->bhssc_opcode = ISCSI_BHS_OPCODE_SCSI_COMMAND; 2336 bhssc->bhssc_flags |= BHSSC_FLAGS_F; 2337 switch (csio->ccb_h.flags & CAM_DIR_MASK) { 2338 case CAM_DIR_IN: 2339 bhssc->bhssc_flags |= BHSSC_FLAGS_R; 2340 break; 2341 case CAM_DIR_OUT: 2342 bhssc->bhssc_flags |= BHSSC_FLAGS_W; 2343 break; 2344 } 2345 2346 if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0) { 2347 switch (csio->tag_action) { 2348 case MSG_HEAD_OF_Q_TAG: 2349 bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_HOQ; 2350 break; 2351 case MSG_ORDERED_Q_TAG: 2352 bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_ORDERED; 2353 break; 2354 case MSG_ACA_TASK: 2355 bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_ACA; 2356 break; 2357 case MSG_SIMPLE_Q_TAG: 2358 default: 2359 bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_SIMPLE; 2360 break; 2361 } 2362 } else 2363 bhssc->bhssc_flags |= BHSSC_FLAGS_ATTR_UNTAGGED; 2364 2365 if (is->is_protocol_level >= 2) { 2366 bhssc->bhssc_pri = (csio->priority << BHSSC_PRI_SHIFT) & 2367 BHSSC_PRI_MASK; 2368 } 2369 2370 bhssc->bhssc_lun = htobe64(CAM_EXTLUN_BYTE_SWIZZLE(ccb->ccb_h.target_lun)); 2371 bhssc->bhssc_initiator_task_tag = initiator_task_tag; 2372 bhssc->bhssc_expected_data_transfer_length = htonl(csio->dxfer_len); 2373 KASSERT(csio->cdb_len <= sizeof(bhssc->bhssc_cdb), 2374 ("unsupported CDB size %zd", (size_t)csio->cdb_len)); 2375 2376 if (csio->ccb_h.flags & CAM_CDB_POINTER) 2377 memcpy(&bhssc->bhssc_cdb, csio->cdb_io.cdb_ptr, csio->cdb_len); 2378 else 2379 memcpy(&bhssc->bhssc_cdb, csio->cdb_io.cdb_bytes, csio->cdb_len); 2380 2381 if (is->is_immediate_data && 2382 (csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) { 2383 len = csio->dxfer_len; 2384 //ISCSI_SESSION_DEBUG(is, "adding %zd of immediate data", len); 2385 if (len > is->is_first_burst_length) { 2386 ISCSI_SESSION_DEBUG(is, "len %zd -> %d", len, is->is_first_burst_length); 2387 len = is->is_first_burst_length; 2388 } 2389 if (len > is->is_conn->ic_max_send_data_segment_length) { 2390 ISCSI_SESSION_DEBUG(is, "len %zd -> %d", len, 2391 is->is_conn->ic_max_send_data_segment_length); 2392 len = is->is_conn->ic_max_send_data_segment_length; 2393 } 2394 2395 error = icl_pdu_append_data(request, csio->data_ptr, len, M_NOWAIT); 2396 if (error != 0) { 2397 iscsi_outstanding_remove(is, io); 2398 icl_pdu_free(request); 2399 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 2400 xpt_freeze_devq(ccb->ccb_h.path, 1); 2401 ISCSI_SESSION_DEBUG(is, "freezing devq"); 2402 } 2403 ccb->ccb_h.status = CAM_RESRC_UNAVAIL | CAM_DEV_QFRZN; 2404 xpt_done(ccb); 2405 return; 2406 } 2407 } 2408 iscsi_pdu_queue_locked(request); 2409 } 2410 2411 static void 2412 iscsi_action(struct cam_sim *sim, union ccb *ccb) 2413 { 2414 struct iscsi_session *is; 2415 2416 is = cam_sim_softc(sim); 2417 2418 ISCSI_SESSION_LOCK_ASSERT(is); 2419 2420 if (is->is_terminating || 2421 (is->is_connected == false && fail_on_disconnection)) { 2422 ccb->ccb_h.status = CAM_DEV_NOT_THERE; 2423 xpt_done(ccb); 2424 return; 2425 } 2426 2427 /* 2428 * Make sure CAM doesn't sneak in a CCB just after freezing the queue. 2429 */ 2430 if (is->is_simq_frozen == true) { 2431 ccb->ccb_h.status &= ~(CAM_SIM_QUEUED | CAM_STATUS_MASK); 2432 ccb->ccb_h.status |= CAM_REQUEUE_REQ; 2433 /* Don't freeze the devq - the SIM queue is already frozen. */ 2434 xpt_done(ccb); 2435 return; 2436 } 2437 2438 switch (ccb->ccb_h.func_code) { 2439 case XPT_PATH_INQ: 2440 { 2441 struct ccb_pathinq *cpi = &ccb->cpi; 2442 2443 cpi->version_num = 1; 2444 cpi->hba_inquiry = PI_TAG_ABLE; 2445 cpi->target_sprt = 0; 2446 cpi->hba_misc = PIM_EXTLUNS; 2447 /* 2448 * XXX: It shouldn't ever be NULL; this could be turned 2449 * into a KASSERT eventually. 2450 */ 2451 if (is->is_conn == NULL) 2452 ISCSI_WARN("NULL conn"); 2453 else if (is->is_conn->ic_unmapped) 2454 cpi->hba_misc |= PIM_UNMAPPED; 2455 cpi->hba_eng_cnt = 0; 2456 cpi->max_target = 0; 2457 /* 2458 * Note that the variable below is only relevant for targets 2459 * that don't claim compliance with anything above SPC2, which 2460 * means they don't support REPORT_LUNS. 2461 */ 2462 cpi->max_lun = 255; 2463 cpi->initiator_id = ~0; 2464 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 2465 strlcpy(cpi->hba_vid, "iSCSI", HBA_IDLEN); 2466 strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 2467 cpi->unit_number = cam_sim_unit(sim); 2468 cpi->bus_id = cam_sim_bus(sim); 2469 cpi->base_transfer_speed = 150000; /* XXX */ 2470 cpi->transport = XPORT_ISCSI; 2471 cpi->transport_version = 0; 2472 cpi->protocol = PROTO_SCSI; 2473 cpi->protocol_version = SCSI_REV_SPC3; 2474 cpi->maxio = maxphys; 2475 cpi->ccb_h.status = CAM_REQ_CMP; 2476 break; 2477 } 2478 case XPT_GET_TRAN_SETTINGS: 2479 { 2480 struct ccb_trans_settings *cts; 2481 struct ccb_trans_settings_scsi *scsi; 2482 2483 cts = &ccb->cts; 2484 scsi = &cts->proto_specific.scsi; 2485 2486 cts->protocol = PROTO_SCSI; 2487 cts->protocol_version = SCSI_REV_SPC3; 2488 cts->transport = XPORT_ISCSI; 2489 cts->transport_version = 0; 2490 scsi->valid = CTS_SCSI_VALID_TQ; 2491 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 2492 cts->ccb_h.status = CAM_REQ_CMP; 2493 break; 2494 } 2495 case XPT_CALC_GEOMETRY: 2496 cam_calc_geometry(&ccb->ccg, /*extended*/1); 2497 ccb->ccb_h.status = CAM_REQ_CMP; 2498 break; 2499 #if 0 2500 /* 2501 * XXX: What's the point? 2502 */ 2503 case XPT_RESET_BUS: 2504 case XPT_TERM_IO: 2505 ISCSI_SESSION_DEBUG(is, "faking success for reset, abort, or term_io"); 2506 ccb->ccb_h.status = CAM_REQ_CMP; 2507 break; 2508 #endif 2509 case XPT_ABORT: 2510 iscsi_action_abort(is, ccb); 2511 return; 2512 case XPT_SCSI_IO: 2513 iscsi_action_scsiio(is, ccb); 2514 return; 2515 default: 2516 #if 0 2517 ISCSI_SESSION_DEBUG(is, "got unsupported code 0x%x", ccb->ccb_h.func_code); 2518 #endif 2519 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 2520 break; 2521 } 2522 xpt_done(ccb); 2523 } 2524 2525 static void 2526 iscsi_terminate_sessions(struct iscsi_softc *sc) 2527 { 2528 struct iscsi_session *is; 2529 2530 sx_slock(&sc->sc_lock); 2531 TAILQ_FOREACH(is, &sc->sc_sessions, is_next) 2532 iscsi_session_terminate(is); 2533 while(!TAILQ_EMPTY(&sc->sc_sessions)) { 2534 ISCSI_DEBUG("waiting for sessions to terminate"); 2535 cv_wait(&sc->sc_cv, &sc->sc_lock); 2536 } 2537 ISCSI_DEBUG("all sessions terminated"); 2538 sx_sunlock(&sc->sc_lock); 2539 } 2540 2541 static void 2542 iscsi_shutdown_pre(struct iscsi_softc *sc) 2543 { 2544 struct iscsi_session *is; 2545 2546 if (!fail_on_shutdown) 2547 return; 2548 2549 /* 2550 * If we have any sessions waiting for reconnection, request 2551 * maintenance thread to fail them immediately instead of waiting 2552 * for reconnect timeout. 2553 * 2554 * This prevents LUNs with mounted filesystems that are supported 2555 * by disconnected iSCSI sessions from hanging, however it will 2556 * fail all queued BIOs. 2557 */ 2558 ISCSI_DEBUG("forcing failing all disconnected sessions due to shutdown"); 2559 2560 fail_on_disconnection = 1; 2561 2562 sx_slock(&sc->sc_lock); 2563 TAILQ_FOREACH(is, &sc->sc_sessions, is_next) { 2564 ISCSI_SESSION_LOCK(is); 2565 if (!is->is_connected) { 2566 ISCSI_SESSION_DEBUG(is, "force failing disconnected session early"); 2567 iscsi_session_reconnect(is); 2568 } 2569 ISCSI_SESSION_UNLOCK(is); 2570 } 2571 sx_sunlock(&sc->sc_lock); 2572 } 2573 2574 static void 2575 iscsi_shutdown_post(struct iscsi_softc *sc) 2576 { 2577 2578 if (!KERNEL_PANICKED()) { 2579 ISCSI_DEBUG("removing all sessions due to shutdown"); 2580 iscsi_terminate_sessions(sc); 2581 } 2582 } 2583 2584 static int 2585 iscsi_load(void) 2586 { 2587 int error; 2588 2589 sc = malloc(sizeof(*sc), M_ISCSI, M_ZERO | M_WAITOK); 2590 sx_init(&sc->sc_lock, "iscsi"); 2591 TAILQ_INIT(&sc->sc_sessions); 2592 cv_init(&sc->sc_cv, "iscsi_cv"); 2593 2594 iscsi_outstanding_zone = uma_zcreate("iscsi_outstanding", 2595 sizeof(struct iscsi_outstanding), NULL, NULL, NULL, NULL, 2596 UMA_ALIGN_PTR, 0); 2597 2598 error = make_dev_p(MAKEDEV_CHECKNAME, &sc->sc_cdev, &iscsi_cdevsw, 2599 NULL, UID_ROOT, GID_WHEEL, 0600, "iscsi"); 2600 if (error != 0) { 2601 ISCSI_WARN("failed to create device node, error %d", error); 2602 return (error); 2603 } 2604 sc->sc_cdev->si_drv1 = sc; 2605 2606 sc->sc_shutdown_pre_eh = EVENTHANDLER_REGISTER(shutdown_pre_sync, 2607 iscsi_shutdown_pre, sc, SHUTDOWN_PRI_FIRST); 2608 /* 2609 * shutdown_post_sync needs to run after filesystem shutdown and before 2610 * CAM shutdown - otherwise when rebooting with an iSCSI session that is 2611 * disconnected but has outstanding requests, dashutdown() will hang on 2612 * cam_periph_runccb(). 2613 */ 2614 sc->sc_shutdown_post_eh = EVENTHANDLER_REGISTER(shutdown_post_sync, 2615 iscsi_shutdown_post, sc, SHUTDOWN_PRI_DEFAULT - 1); 2616 2617 return (0); 2618 } 2619 2620 static int 2621 iscsi_unload(void) 2622 { 2623 2624 /* Awaken any threads asleep in iscsi_ioctl(). */ 2625 sx_xlock(&sc->sc_lock); 2626 sc->sc_unloading = true; 2627 cv_signal(&sc->sc_cv); 2628 sx_xunlock(&sc->sc_lock); 2629 2630 if (sc->sc_cdev != NULL) { 2631 ISCSI_DEBUG("removing device node"); 2632 destroy_dev(sc->sc_cdev); 2633 ISCSI_DEBUG("device node removed"); 2634 } 2635 2636 if (sc->sc_shutdown_pre_eh != NULL) 2637 EVENTHANDLER_DEREGISTER(shutdown_pre_sync, sc->sc_shutdown_pre_eh); 2638 if (sc->sc_shutdown_post_eh != NULL) 2639 EVENTHANDLER_DEREGISTER(shutdown_post_sync, sc->sc_shutdown_post_eh); 2640 2641 iscsi_terminate_sessions(sc); 2642 2643 uma_zdestroy(iscsi_outstanding_zone); 2644 sx_destroy(&sc->sc_lock); 2645 cv_destroy(&sc->sc_cv); 2646 free(sc, M_ISCSI); 2647 return (0); 2648 } 2649 2650 static int 2651 iscsi_quiesce(void) 2652 { 2653 sx_slock(&sc->sc_lock); 2654 if (!TAILQ_EMPTY(&sc->sc_sessions)) { 2655 sx_sunlock(&sc->sc_lock); 2656 return (EBUSY); 2657 } 2658 sx_sunlock(&sc->sc_lock); 2659 return (0); 2660 } 2661 2662 static int 2663 iscsi_modevent(module_t mod, int what, void *arg) 2664 { 2665 int error; 2666 2667 switch (what) { 2668 case MOD_LOAD: 2669 error = iscsi_load(); 2670 break; 2671 case MOD_UNLOAD: 2672 error = iscsi_unload(); 2673 break; 2674 case MOD_QUIESCE: 2675 error = iscsi_quiesce(); 2676 break; 2677 default: 2678 error = EINVAL; 2679 break; 2680 } 2681 return (error); 2682 } 2683 2684 moduledata_t iscsi_data = { 2685 "iscsi", 2686 iscsi_modevent, 2687 0 2688 }; 2689 2690 DECLARE_MODULE(iscsi, iscsi_data, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); 2691 MODULE_DEPEND(iscsi, cam, 1, 1, 1); 2692 MODULE_DEPEND(iscsi, icl, 1, 1, 1); 2693