1 /*- 2 * Copyright (c) 2012 The FreeBSD Foundation 3 * All rights reserved. 4 * 5 * This software was developed by Edward Tomasz Napierala under sponsorship 6 * from the FreeBSD Foundation. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $FreeBSD$ 30 */ 31 32 /* 33 * CTL frontend for the iSCSI protocol. 34 */ 35 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 #include <sys/param.h> 40 #include <sys/capsicum.h> 41 #include <sys/condvar.h> 42 #include <sys/file.h> 43 #include <sys/kernel.h> 44 #include <sys/kthread.h> 45 #include <sys/lock.h> 46 #include <sys/malloc.h> 47 #include <sys/module.h> 48 #include <sys/mutex.h> 49 #include <sys/queue.h> 50 #include <sys/sbuf.h> 51 #include <sys/sysctl.h> 52 #include <sys/systm.h> 53 #include <sys/uio.h> 54 #include <sys/unistd.h> 55 #include <vm/uma.h> 56 57 #include <cam/scsi/scsi_all.h> 58 #include <cam/scsi/scsi_da.h> 59 #include <cam/ctl/ctl_io.h> 60 #include <cam/ctl/ctl.h> 61 #include <cam/ctl/ctl_backend.h> 62 #include <cam/ctl/ctl_error.h> 63 #include <cam/ctl/ctl_frontend.h> 64 #include <cam/ctl/ctl_debug.h> 65 #include <cam/ctl/ctl_ha.h> 66 #include <cam/ctl/ctl_ioctl.h> 67 #include <cam/ctl/ctl_private.h> 68 69 #include <dev/iscsi/icl.h> 70 #include <dev/iscsi/icl_wrappers.h> 71 #include <dev/iscsi/iscsi_proto.h> 72 #include <cam/ctl/ctl_frontend_iscsi.h> 73 74 #ifdef ICL_KERNEL_PROXY 75 #include <sys/socketvar.h> 76 #endif 77 78 #ifdef ICL_KERNEL_PROXY 79 FEATURE(cfiscsi_kernel_proxy, "iSCSI target built with ICL_KERNEL_PROXY"); 80 #endif 81 82 static MALLOC_DEFINE(M_CFISCSI, "cfiscsi", "Memory used for CTL iSCSI frontend"); 83 static uma_zone_t cfiscsi_data_wait_zone; 84 85 SYSCTL_NODE(_kern_cam_ctl, OID_AUTO, iscsi, CTLFLAG_RD, 0, 86 "CAM Target Layer iSCSI Frontend"); 87 static int debug = 1; 88 SYSCTL_INT(_kern_cam_ctl_iscsi, OID_AUTO, debug, CTLFLAG_RWTUN, 89 &debug, 1, "Enable debug messages"); 90 static int ping_timeout = 5; 91 SYSCTL_INT(_kern_cam_ctl_iscsi, OID_AUTO, ping_timeout, CTLFLAG_RWTUN, 92 &ping_timeout, 5, "Interval between ping (NOP-Out) requests, in seconds"); 93 static int login_timeout = 60; 94 SYSCTL_INT(_kern_cam_ctl_iscsi, OID_AUTO, login_timeout, CTLFLAG_RWTUN, 95 &login_timeout, 60, "Time to wait for ctld(8) to finish Login Phase, in seconds"); 96 static int maxcmdsn_delta = 256; 97 SYSCTL_INT(_kern_cam_ctl_iscsi, OID_AUTO, maxcmdsn_delta, CTLFLAG_RWTUN, 98 &maxcmdsn_delta, 256, "Number of commands the initiator can send " 99 "without confirmation"); 100 101 #define CFISCSI_DEBUG(X, ...) \ 102 do { \ 103 if (debug > 1) { \ 104 printf("%s: " X "\n", \ 105 __func__, ## __VA_ARGS__); \ 106 } \ 107 } while (0) 108 109 #define CFISCSI_WARN(X, ...) \ 110 do { \ 111 if (debug > 0) { \ 112 printf("WARNING: %s: " X "\n", \ 113 __func__, ## __VA_ARGS__); \ 114 } \ 115 } while (0) 116 117 #define CFISCSI_SESSION_DEBUG(S, X, ...) \ 118 do { \ 119 if (debug > 1) { \ 120 printf("%s: %s (%s): " X "\n", \ 121 __func__, S->cs_initiator_addr, \ 122 S->cs_initiator_name, ## __VA_ARGS__); \ 123 } \ 124 } while (0) 125 126 #define CFISCSI_SESSION_WARN(S, X, ...) \ 127 do { \ 128 if (debug > 0) { \ 129 printf("WARNING: %s (%s): " X "\n", \ 130 S->cs_initiator_addr, \ 131 S->cs_initiator_name, ## __VA_ARGS__); \ 132 } \ 133 } while (0) 134 135 #define CFISCSI_SESSION_LOCK(X) mtx_lock(&X->cs_lock) 136 #define CFISCSI_SESSION_UNLOCK(X) mtx_unlock(&X->cs_lock) 137 #define CFISCSI_SESSION_LOCK_ASSERT(X) mtx_assert(&X->cs_lock, MA_OWNED) 138 139 #define CONN_SESSION(X) ((struct cfiscsi_session *)(X)->ic_prv0) 140 #define PDU_SESSION(X) CONN_SESSION((X)->ip_conn) 141 #define PDU_EXPDATASN(X) (X)->ip_prv0 142 #define PDU_TOTAL_TRANSFER_LEN(X) (X)->ip_prv1 143 #define PDU_R2TSN(X) (X)->ip_prv2 144 145 int cfiscsi_init(void); 146 static void cfiscsi_online(void *arg); 147 static void cfiscsi_offline(void *arg); 148 static int cfiscsi_info(void *arg, struct sbuf *sb); 149 static int cfiscsi_ioctl(struct cdev *dev, 150 u_long cmd, caddr_t addr, int flag, struct thread *td); 151 static void cfiscsi_datamove(union ctl_io *io); 152 static void cfiscsi_datamove_in(union ctl_io *io); 153 static void cfiscsi_datamove_out(union ctl_io *io); 154 static void cfiscsi_done(union ctl_io *io); 155 static bool cfiscsi_pdu_update_cmdsn(const struct icl_pdu *request); 156 static void cfiscsi_pdu_handle_nop_out(struct icl_pdu *request); 157 static void cfiscsi_pdu_handle_scsi_command(struct icl_pdu *request); 158 static void cfiscsi_pdu_handle_task_request(struct icl_pdu *request); 159 static void cfiscsi_pdu_handle_data_out(struct icl_pdu *request); 160 static void cfiscsi_pdu_handle_logout_request(struct icl_pdu *request); 161 static void cfiscsi_session_terminate(struct cfiscsi_session *cs); 162 static struct cfiscsi_data_wait *cfiscsi_data_wait_new( 163 struct cfiscsi_session *cs, union ctl_io *io, 164 uint32_t initiator_task_tag, 165 uint32_t *target_transfer_tagp); 166 static void cfiscsi_data_wait_free(struct cfiscsi_session *cs, 167 struct cfiscsi_data_wait *cdw); 168 static struct cfiscsi_target *cfiscsi_target_find(struct cfiscsi_softc 169 *softc, const char *name, uint16_t tag); 170 static struct cfiscsi_target *cfiscsi_target_find_or_create( 171 struct cfiscsi_softc *softc, const char *name, const char *alias, 172 uint16_t tag); 173 static void cfiscsi_target_release(struct cfiscsi_target *ct); 174 static void cfiscsi_session_delete(struct cfiscsi_session *cs); 175 176 static struct cfiscsi_softc cfiscsi_softc; 177 extern struct ctl_softc *control_softc; 178 179 static struct ctl_frontend cfiscsi_frontend = 180 { 181 .name = "iscsi", 182 .init = cfiscsi_init, 183 .ioctl = cfiscsi_ioctl, 184 }; 185 CTL_FRONTEND_DECLARE(ctlcfiscsi, cfiscsi_frontend); 186 MODULE_DEPEND(ctlcfiscsi, icl, 1, 1, 1); 187 188 static struct icl_pdu * 189 cfiscsi_pdu_new_response(struct icl_pdu *request, int flags) 190 { 191 192 return (icl_pdu_new(request->ip_conn, flags)); 193 } 194 195 static bool 196 cfiscsi_pdu_update_cmdsn(const struct icl_pdu *request) 197 { 198 const struct iscsi_bhs_scsi_command *bhssc; 199 struct cfiscsi_session *cs; 200 uint32_t cmdsn, expstatsn; 201 202 cs = PDU_SESSION(request); 203 204 /* 205 * Every incoming PDU - not just NOP-Out - resets the ping timer. 206 * The purpose of the timeout is to reset the connection when it stalls; 207 * we don't want this to happen when NOP-In or NOP-Out ends up delayed 208 * in some queue. 209 * 210 * XXX: Locking? 211 */ 212 cs->cs_timeout = 0; 213 214 /* 215 * Data-Out PDUs don't contain CmdSN. 216 */ 217 if ((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) == 218 ISCSI_BHS_OPCODE_SCSI_DATA_OUT) 219 return (false); 220 221 /* 222 * We're only using fields common for all the request 223 * (initiator -> target) PDUs. 224 */ 225 bhssc = (const struct iscsi_bhs_scsi_command *)request->ip_bhs; 226 cmdsn = ntohl(bhssc->bhssc_cmdsn); 227 expstatsn = ntohl(bhssc->bhssc_expstatsn); 228 229 CFISCSI_SESSION_LOCK(cs); 230 #if 0 231 if (expstatsn != cs->cs_statsn) { 232 CFISCSI_SESSION_DEBUG(cs, "received PDU with ExpStatSN %d, " 233 "while current StatSN is %d", expstatsn, 234 cs->cs_statsn); 235 } 236 #endif 237 238 if ((request->ip_bhs->bhs_opcode & ISCSI_BHS_OPCODE_IMMEDIATE) == 0) { 239 /* 240 * The target MUST silently ignore any non-immediate command 241 * outside of this range. 242 */ 243 if (ISCSI_SNLT(cmdsn, cs->cs_cmdsn) || 244 ISCSI_SNGT(cmdsn, cs->cs_cmdsn + maxcmdsn_delta)) { 245 CFISCSI_SESSION_UNLOCK(cs); 246 CFISCSI_SESSION_WARN(cs, "received PDU with CmdSN %u, " 247 "while expected %u", cmdsn, cs->cs_cmdsn); 248 return (true); 249 } 250 251 /* 252 * We don't support multiple connections now, so any 253 * discontinuity in CmdSN means lost PDUs. Since we don't 254 * support PDU retransmission -- terminate the connection. 255 */ 256 if (cmdsn != cs->cs_cmdsn) { 257 CFISCSI_SESSION_UNLOCK(cs); 258 CFISCSI_SESSION_WARN(cs, "received PDU with CmdSN %u, " 259 "while expected %u; dropping connection", 260 cmdsn, cs->cs_cmdsn); 261 cfiscsi_session_terminate(cs); 262 return (true); 263 } 264 cs->cs_cmdsn++; 265 } 266 267 CFISCSI_SESSION_UNLOCK(cs); 268 269 return (false); 270 } 271 272 static void 273 cfiscsi_pdu_handle(struct icl_pdu *request) 274 { 275 struct cfiscsi_session *cs; 276 bool ignore; 277 278 cs = PDU_SESSION(request); 279 280 ignore = cfiscsi_pdu_update_cmdsn(request); 281 if (ignore) { 282 icl_pdu_free(request); 283 return; 284 } 285 286 /* 287 * Handle the PDU; this includes e.g. receiving the remaining 288 * part of PDU and submitting the SCSI command to CTL 289 * or queueing a reply. The handling routine is responsible 290 * for freeing the PDU when it's no longer needed. 291 */ 292 switch (request->ip_bhs->bhs_opcode & 293 ~ISCSI_BHS_OPCODE_IMMEDIATE) { 294 case ISCSI_BHS_OPCODE_NOP_OUT: 295 cfiscsi_pdu_handle_nop_out(request); 296 break; 297 case ISCSI_BHS_OPCODE_SCSI_COMMAND: 298 cfiscsi_pdu_handle_scsi_command(request); 299 break; 300 case ISCSI_BHS_OPCODE_TASK_REQUEST: 301 cfiscsi_pdu_handle_task_request(request); 302 break; 303 case ISCSI_BHS_OPCODE_SCSI_DATA_OUT: 304 cfiscsi_pdu_handle_data_out(request); 305 break; 306 case ISCSI_BHS_OPCODE_LOGOUT_REQUEST: 307 cfiscsi_pdu_handle_logout_request(request); 308 break; 309 default: 310 CFISCSI_SESSION_WARN(cs, "received PDU with unsupported " 311 "opcode 0x%x; dropping connection", 312 request->ip_bhs->bhs_opcode); 313 icl_pdu_free(request); 314 cfiscsi_session_terminate(cs); 315 } 316 317 } 318 319 static void 320 cfiscsi_receive_callback(struct icl_pdu *request) 321 { 322 struct cfiscsi_session *cs; 323 324 cs = PDU_SESSION(request); 325 326 #ifdef ICL_KERNEL_PROXY 327 if (cs->cs_waiting_for_ctld || cs->cs_login_phase) { 328 if (cs->cs_login_pdu == NULL) 329 cs->cs_login_pdu = request; 330 else 331 icl_pdu_free(request); 332 cv_signal(&cs->cs_login_cv); 333 return; 334 } 335 #endif 336 337 cfiscsi_pdu_handle(request); 338 } 339 340 static void 341 cfiscsi_error_callback(struct icl_conn *ic) 342 { 343 struct cfiscsi_session *cs; 344 345 cs = CONN_SESSION(ic); 346 347 CFISCSI_SESSION_WARN(cs, "connection error; dropping connection"); 348 cfiscsi_session_terminate(cs); 349 } 350 351 static int 352 cfiscsi_pdu_prepare(struct icl_pdu *response) 353 { 354 struct cfiscsi_session *cs; 355 struct iscsi_bhs_scsi_response *bhssr; 356 bool advance_statsn = true; 357 358 cs = PDU_SESSION(response); 359 360 CFISCSI_SESSION_LOCK_ASSERT(cs); 361 362 /* 363 * We're only using fields common for all the response 364 * (target -> initiator) PDUs. 365 */ 366 bhssr = (struct iscsi_bhs_scsi_response *)response->ip_bhs; 367 368 /* 369 * 10.8.3: "The StatSN for this connection is not advanced 370 * after this PDU is sent." 371 */ 372 if (bhssr->bhssr_opcode == ISCSI_BHS_OPCODE_R2T) 373 advance_statsn = false; 374 375 /* 376 * 10.19.2: "However, when the Initiator Task Tag is set to 0xffffffff, 377 * StatSN for the connection is not advanced after this PDU is sent." 378 */ 379 if (bhssr->bhssr_opcode == ISCSI_BHS_OPCODE_NOP_IN && 380 bhssr->bhssr_initiator_task_tag == 0xffffffff) 381 advance_statsn = false; 382 383 /* 384 * See the comment below - StatSN is not meaningful and must 385 * not be advanced. 386 */ 387 if (bhssr->bhssr_opcode == ISCSI_BHS_OPCODE_SCSI_DATA_IN && 388 (bhssr->bhssr_flags & BHSDI_FLAGS_S) == 0) 389 advance_statsn = false; 390 391 /* 392 * 10.7.3: "The fields StatSN, Status, and Residual Count 393 * only have meaningful content if the S bit is set to 1." 394 */ 395 if (bhssr->bhssr_opcode != ISCSI_BHS_OPCODE_SCSI_DATA_IN || 396 (bhssr->bhssr_flags & BHSDI_FLAGS_S)) 397 bhssr->bhssr_statsn = htonl(cs->cs_statsn); 398 bhssr->bhssr_expcmdsn = htonl(cs->cs_cmdsn); 399 bhssr->bhssr_maxcmdsn = htonl(cs->cs_cmdsn + maxcmdsn_delta); 400 401 if (advance_statsn) 402 cs->cs_statsn++; 403 404 return (0); 405 } 406 407 static void 408 cfiscsi_pdu_queue(struct icl_pdu *response) 409 { 410 struct cfiscsi_session *cs; 411 412 cs = PDU_SESSION(response); 413 414 CFISCSI_SESSION_LOCK(cs); 415 cfiscsi_pdu_prepare(response); 416 icl_pdu_queue(response); 417 CFISCSI_SESSION_UNLOCK(cs); 418 } 419 420 static uint32_t 421 cfiscsi_decode_lun(uint64_t encoded) 422 { 423 uint8_t lun[8]; 424 uint32_t result; 425 426 /* 427 * The LUN field in iSCSI PDUs may look like an ordinary 64 bit number, 428 * but is in fact an evil, multidimensional structure defined 429 * in SCSI Architecture Model 5 (SAM-5), section 4.6. 430 */ 431 memcpy(lun, &encoded, sizeof(lun)); 432 switch (lun[0] & 0xC0) { 433 case 0x00: 434 if ((lun[0] & 0x3f) != 0 || lun[2] != 0 || lun[3] != 0 || 435 lun[4] != 0 || lun[5] != 0 || lun[6] != 0 || lun[7] != 0) { 436 CFISCSI_WARN("malformed LUN " 437 "(peripheral device addressing method): 0x%jx", 438 (uintmax_t)encoded); 439 result = 0xffffffff; 440 break; 441 } 442 result = lun[1]; 443 break; 444 case 0x40: 445 if (lun[2] != 0 || lun[3] != 0 || lun[4] != 0 || lun[5] != 0 || 446 lun[6] != 0 || lun[7] != 0) { 447 CFISCSI_WARN("malformed LUN " 448 "(flat address space addressing method): 0x%jx", 449 (uintmax_t)encoded); 450 result = 0xffffffff; 451 break; 452 } 453 result = ((lun[0] & 0x3f) << 8) + lun[1]; 454 break; 455 case 0xC0: 456 if (lun[0] != 0xD2 || lun[4] != 0 || lun[5] != 0 || 457 lun[6] != 0 || lun[7] != 0) { 458 CFISCSI_WARN("malformed LUN (extended flat " 459 "address space addressing method): 0x%jx", 460 (uintmax_t)encoded); 461 result = 0xffffffff; 462 break; 463 } 464 result = (lun[1] << 16) + (lun[2] << 8) + lun[3]; 465 default: 466 CFISCSI_WARN("unsupported LUN format 0x%jx", 467 (uintmax_t)encoded); 468 result = 0xffffffff; 469 break; 470 } 471 472 return (result); 473 } 474 475 static void 476 cfiscsi_pdu_handle_nop_out(struct icl_pdu *request) 477 { 478 struct cfiscsi_session *cs; 479 struct iscsi_bhs_nop_out *bhsno; 480 struct iscsi_bhs_nop_in *bhsni; 481 struct icl_pdu *response; 482 void *data = NULL; 483 size_t datasize; 484 int error; 485 486 cs = PDU_SESSION(request); 487 bhsno = (struct iscsi_bhs_nop_out *)request->ip_bhs; 488 489 if (bhsno->bhsno_initiator_task_tag == 0xffffffff) { 490 /* 491 * Nothing to do, iscsi_pdu_update_statsn() already 492 * zeroed the timeout. 493 */ 494 icl_pdu_free(request); 495 return; 496 } 497 498 datasize = icl_pdu_data_segment_length(request); 499 if (datasize > 0) { 500 data = malloc(datasize, M_CFISCSI, M_NOWAIT | M_ZERO); 501 if (data == NULL) { 502 CFISCSI_SESSION_WARN(cs, "failed to allocate memory; " 503 "dropping connection"); 504 icl_pdu_free(request); 505 cfiscsi_session_terminate(cs); 506 return; 507 } 508 icl_pdu_get_data(request, 0, data, datasize); 509 } 510 511 response = cfiscsi_pdu_new_response(request, M_NOWAIT); 512 if (response == NULL) { 513 CFISCSI_SESSION_WARN(cs, "failed to allocate memory; " 514 "droppping connection"); 515 free(data, M_CFISCSI); 516 icl_pdu_free(request); 517 cfiscsi_session_terminate(cs); 518 return; 519 } 520 bhsni = (struct iscsi_bhs_nop_in *)response->ip_bhs; 521 bhsni->bhsni_opcode = ISCSI_BHS_OPCODE_NOP_IN; 522 bhsni->bhsni_flags = 0x80; 523 bhsni->bhsni_initiator_task_tag = bhsno->bhsno_initiator_task_tag; 524 bhsni->bhsni_target_transfer_tag = 0xffffffff; 525 if (datasize > 0) { 526 error = icl_pdu_append_data(response, data, datasize, M_NOWAIT); 527 if (error != 0) { 528 CFISCSI_SESSION_WARN(cs, "failed to allocate memory; " 529 "dropping connection"); 530 free(data, M_CFISCSI); 531 icl_pdu_free(request); 532 icl_pdu_free(response); 533 cfiscsi_session_terminate(cs); 534 return; 535 } 536 free(data, M_CFISCSI); 537 } 538 539 icl_pdu_free(request); 540 cfiscsi_pdu_queue(response); 541 } 542 543 static void 544 cfiscsi_pdu_handle_scsi_command(struct icl_pdu *request) 545 { 546 struct iscsi_bhs_scsi_command *bhssc; 547 struct cfiscsi_session *cs; 548 union ctl_io *io; 549 int error; 550 551 cs = PDU_SESSION(request); 552 bhssc = (struct iscsi_bhs_scsi_command *)request->ip_bhs; 553 //CFISCSI_SESSION_DEBUG(cs, "initiator task tag 0x%x", 554 // bhssc->bhssc_initiator_task_tag); 555 556 if (request->ip_data_len > 0 && cs->cs_immediate_data == false) { 557 CFISCSI_SESSION_WARN(cs, "unsolicited data with " 558 "ImmediateData=No; dropping connection"); 559 icl_pdu_free(request); 560 cfiscsi_session_terminate(cs); 561 return; 562 } 563 io = ctl_alloc_io(cs->cs_target->ct_port.ctl_pool_ref); 564 ctl_zero_io(io); 565 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = request; 566 io->io_hdr.io_type = CTL_IO_SCSI; 567 io->io_hdr.nexus.initid.id = cs->cs_ctl_initid; 568 io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port; 569 io->io_hdr.nexus.targ_target.id = 0; 570 io->io_hdr.nexus.targ_lun = cfiscsi_decode_lun(bhssc->bhssc_lun); 571 io->scsiio.tag_num = bhssc->bhssc_initiator_task_tag; 572 switch ((bhssc->bhssc_flags & BHSSC_FLAGS_ATTR)) { 573 case BHSSC_FLAGS_ATTR_UNTAGGED: 574 io->scsiio.tag_type = CTL_TAG_UNTAGGED; 575 break; 576 case BHSSC_FLAGS_ATTR_SIMPLE: 577 io->scsiio.tag_type = CTL_TAG_SIMPLE; 578 break; 579 case BHSSC_FLAGS_ATTR_ORDERED: 580 io->scsiio.tag_type = CTL_TAG_ORDERED; 581 break; 582 case BHSSC_FLAGS_ATTR_HOQ: 583 io->scsiio.tag_type = CTL_TAG_HEAD_OF_QUEUE; 584 break; 585 case BHSSC_FLAGS_ATTR_ACA: 586 io->scsiio.tag_type = CTL_TAG_ACA; 587 break; 588 default: 589 io->scsiio.tag_type = CTL_TAG_UNTAGGED; 590 CFISCSI_SESSION_WARN(cs, "unhandled tag type %d", 591 bhssc->bhssc_flags & BHSSC_FLAGS_ATTR); 592 break; 593 } 594 io->scsiio.cdb_len = sizeof(bhssc->bhssc_cdb); /* Which is 16. */ 595 memcpy(io->scsiio.cdb, bhssc->bhssc_cdb, sizeof(bhssc->bhssc_cdb)); 596 refcount_acquire(&cs->cs_outstanding_ctl_pdus); 597 error = ctl_queue(io); 598 if (error != CTL_RETVAL_COMPLETE) { 599 CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d; " 600 "dropping connection", error); 601 ctl_free_io(io); 602 refcount_release(&cs->cs_outstanding_ctl_pdus); 603 icl_pdu_free(request); 604 cfiscsi_session_terminate(cs); 605 } 606 } 607 608 static void 609 cfiscsi_pdu_handle_task_request(struct icl_pdu *request) 610 { 611 struct iscsi_bhs_task_management_request *bhstmr; 612 struct iscsi_bhs_task_management_response *bhstmr2; 613 struct icl_pdu *response; 614 struct cfiscsi_session *cs; 615 union ctl_io *io; 616 int error; 617 618 cs = PDU_SESSION(request); 619 bhstmr = (struct iscsi_bhs_task_management_request *)request->ip_bhs; 620 io = ctl_alloc_io(cs->cs_target->ct_port.ctl_pool_ref); 621 ctl_zero_io(io); 622 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = request; 623 io->io_hdr.io_type = CTL_IO_TASK; 624 io->io_hdr.nexus.initid.id = cs->cs_ctl_initid; 625 io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port; 626 io->io_hdr.nexus.targ_target.id = 0; 627 io->io_hdr.nexus.targ_lun = cfiscsi_decode_lun(bhstmr->bhstmr_lun); 628 io->taskio.tag_type = CTL_TAG_SIMPLE; /* XXX */ 629 630 switch (bhstmr->bhstmr_function & ~0x80) { 631 case BHSTMR_FUNCTION_ABORT_TASK: 632 #if 0 633 CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_ABORT_TASK"); 634 #endif 635 io->taskio.task_action = CTL_TASK_ABORT_TASK; 636 io->taskio.tag_num = bhstmr->bhstmr_referenced_task_tag; 637 break; 638 case BHSTMR_FUNCTION_ABORT_TASK_SET: 639 #if 0 640 CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_ABORT_TASK_SET"); 641 #endif 642 io->taskio.task_action = CTL_TASK_ABORT_TASK_SET; 643 break; 644 case BHSTMR_FUNCTION_LOGICAL_UNIT_RESET: 645 #if 0 646 CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_LOGICAL_UNIT_RESET"); 647 #endif 648 io->taskio.task_action = CTL_TASK_LUN_RESET; 649 break; 650 case BHSTMR_FUNCTION_TARGET_WARM_RESET: 651 #if 0 652 CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_TARGET_WARM_RESET"); 653 #endif 654 io->taskio.task_action = CTL_TASK_TARGET_RESET; 655 break; 656 default: 657 CFISCSI_SESSION_DEBUG(cs, "unsupported function 0x%x", 658 bhstmr->bhstmr_function & ~0x80); 659 ctl_free_io(io); 660 661 response = cfiscsi_pdu_new_response(request, M_NOWAIT); 662 if (response == NULL) { 663 CFISCSI_SESSION_WARN(cs, "failed to allocate memory; " 664 "dropping connection"); 665 icl_pdu_free(request); 666 cfiscsi_session_terminate(cs); 667 return; 668 } 669 bhstmr2 = (struct iscsi_bhs_task_management_response *) 670 response->ip_bhs; 671 bhstmr2->bhstmr_opcode = ISCSI_BHS_OPCODE_TASK_RESPONSE; 672 bhstmr2->bhstmr_flags = 0x80; 673 bhstmr2->bhstmr_response = 674 BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED; 675 bhstmr2->bhstmr_initiator_task_tag = 676 bhstmr->bhstmr_initiator_task_tag; 677 icl_pdu_free(request); 678 cfiscsi_pdu_queue(response); 679 return; 680 } 681 682 refcount_acquire(&cs->cs_outstanding_ctl_pdus); 683 error = ctl_queue(io); 684 if (error != CTL_RETVAL_COMPLETE) { 685 CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d; " 686 "dropping connection", error); 687 ctl_free_io(io); 688 refcount_release(&cs->cs_outstanding_ctl_pdus); 689 icl_pdu_free(request); 690 cfiscsi_session_terminate(cs); 691 } 692 } 693 694 static bool 695 cfiscsi_handle_data_segment(struct icl_pdu *request, struct cfiscsi_data_wait *cdw) 696 { 697 struct iscsi_bhs_data_out *bhsdo; 698 struct cfiscsi_session *cs; 699 struct ctl_sg_entry ctl_sg_entry, *ctl_sglist; 700 size_t copy_len, len, off, buffer_offset; 701 int ctl_sg_count; 702 union ctl_io *io; 703 704 cs = PDU_SESSION(request); 705 706 KASSERT((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) == 707 ISCSI_BHS_OPCODE_SCSI_DATA_OUT || 708 (request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) == 709 ISCSI_BHS_OPCODE_SCSI_COMMAND, 710 ("bad opcode 0x%x", request->ip_bhs->bhs_opcode)); 711 712 /* 713 * We're only using fields common for Data-Out and SCSI Command PDUs. 714 */ 715 bhsdo = (struct iscsi_bhs_data_out *)request->ip_bhs; 716 717 io = cdw->cdw_ctl_io; 718 KASSERT((io->io_hdr.flags & CTL_FLAG_DATA_MASK) != CTL_FLAG_DATA_IN, 719 ("CTL_FLAG_DATA_IN")); 720 721 #if 0 722 CFISCSI_SESSION_DEBUG(cs, "received %zd bytes out of %d", 723 request->ip_data_len, io->scsiio.kern_total_len); 724 #endif 725 726 if (io->scsiio.kern_sg_entries > 0) { 727 ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr; 728 ctl_sg_count = io->scsiio.kern_sg_entries; 729 } else { 730 ctl_sglist = &ctl_sg_entry; 731 ctl_sglist->addr = io->scsiio.kern_data_ptr; 732 ctl_sglist->len = io->scsiio.kern_data_len; 733 ctl_sg_count = 1; 734 } 735 736 if ((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) == 737 ISCSI_BHS_OPCODE_SCSI_DATA_OUT) 738 buffer_offset = ntohl(bhsdo->bhsdo_buffer_offset); 739 else 740 buffer_offset = 0; 741 len = icl_pdu_data_segment_length(request); 742 743 /* 744 * Make sure the offset, as sent by the initiator, matches the offset 745 * we're supposed to be at in the scatter-gather list. 746 */ 747 if (buffer_offset > 748 io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled || 749 buffer_offset + len <= 750 io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled) { 751 CFISCSI_SESSION_WARN(cs, "received bad buffer offset %zd, " 752 "expected %zd; dropping connection", buffer_offset, 753 (size_t)io->scsiio.kern_rel_offset + 754 (size_t)io->scsiio.ext_data_filled); 755 ctl_set_data_phase_error(&io->scsiio); 756 cfiscsi_session_terminate(cs); 757 return (true); 758 } 759 760 /* 761 * This is the offset within the PDU data segment, as opposed 762 * to buffer_offset, which is the offset within the task (SCSI 763 * command). 764 */ 765 off = io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled - 766 buffer_offset; 767 768 /* 769 * Iterate over the scatter/gather segments, filling them with data 770 * from the PDU data segment. Note that this can get called multiple 771 * times for one SCSI command; the cdw structure holds state for the 772 * scatter/gather list. 773 */ 774 for (;;) { 775 KASSERT(cdw->cdw_sg_index < ctl_sg_count, 776 ("cdw->cdw_sg_index >= ctl_sg_count")); 777 if (cdw->cdw_sg_len == 0) { 778 cdw->cdw_sg_addr = ctl_sglist[cdw->cdw_sg_index].addr; 779 cdw->cdw_sg_len = ctl_sglist[cdw->cdw_sg_index].len; 780 } 781 KASSERT(off <= len, ("len > off")); 782 copy_len = len - off; 783 if (copy_len > cdw->cdw_sg_len) 784 copy_len = cdw->cdw_sg_len; 785 786 icl_pdu_get_data(request, off, cdw->cdw_sg_addr, copy_len); 787 cdw->cdw_sg_addr += copy_len; 788 cdw->cdw_sg_len -= copy_len; 789 off += copy_len; 790 io->scsiio.ext_data_filled += copy_len; 791 792 if (cdw->cdw_sg_len == 0) { 793 /* 794 * End of current segment. 795 */ 796 if (cdw->cdw_sg_index == ctl_sg_count - 1) { 797 /* 798 * Last segment in scatter/gather list. 799 */ 800 break; 801 } 802 cdw->cdw_sg_index++; 803 } 804 805 if (off == len) { 806 /* 807 * End of PDU payload. 808 */ 809 break; 810 } 811 } 812 813 if (len > off) { 814 /* 815 * In case of unsolicited data, it's possible that the buffer 816 * provided by CTL is smaller than negotiated FirstBurstLength. 817 * Just ignore the superfluous data; will ask for them with R2T 818 * on next call to cfiscsi_datamove(). 819 * 820 * This obviously can only happen with SCSI Command PDU. 821 */ 822 if ((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) == 823 ISCSI_BHS_OPCODE_SCSI_COMMAND) 824 return (true); 825 826 CFISCSI_SESSION_WARN(cs, "received too much data: got %zd bytes, " 827 "expected %zd; dropping connection", 828 icl_pdu_data_segment_length(request), off); 829 ctl_set_data_phase_error(&io->scsiio); 830 cfiscsi_session_terminate(cs); 831 return (true); 832 } 833 834 if (io->scsiio.ext_data_filled == cdw->cdw_r2t_end && 835 (bhsdo->bhsdo_flags & BHSDO_FLAGS_F) == 0) { 836 CFISCSI_SESSION_WARN(cs, "got the final packet without " 837 "the F flag; flags = 0x%x; dropping connection", 838 bhsdo->bhsdo_flags); 839 ctl_set_data_phase_error(&io->scsiio); 840 cfiscsi_session_terminate(cs); 841 return (true); 842 } 843 844 if (io->scsiio.ext_data_filled != cdw->cdw_r2t_end && 845 (bhsdo->bhsdo_flags & BHSDO_FLAGS_F) != 0) { 846 if ((request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) == 847 ISCSI_BHS_OPCODE_SCSI_DATA_OUT) { 848 CFISCSI_SESSION_WARN(cs, "got the final packet, but the " 849 "transmitted size was %zd bytes instead of %d; " 850 "dropping connection", 851 (size_t)io->scsiio.ext_data_filled, 852 cdw->cdw_r2t_end); 853 ctl_set_data_phase_error(&io->scsiio); 854 cfiscsi_session_terminate(cs); 855 return (true); 856 } else { 857 /* 858 * For SCSI Command PDU, this just means we need to 859 * solicit more data by sending R2T. 860 */ 861 return (false); 862 } 863 } 864 865 if (io->scsiio.ext_data_filled == cdw->cdw_r2t_end) { 866 #if 0 867 CFISCSI_SESSION_DEBUG(cs, "no longer expecting Data-Out with target " 868 "transfer tag 0x%x", cdw->cdw_target_transfer_tag); 869 #endif 870 871 return (true); 872 } 873 874 return (false); 875 } 876 877 static void 878 cfiscsi_pdu_handle_data_out(struct icl_pdu *request) 879 { 880 struct iscsi_bhs_data_out *bhsdo; 881 struct cfiscsi_session *cs; 882 struct cfiscsi_data_wait *cdw = NULL; 883 union ctl_io *io; 884 bool done; 885 886 cs = PDU_SESSION(request); 887 bhsdo = (struct iscsi_bhs_data_out *)request->ip_bhs; 888 889 CFISCSI_SESSION_LOCK(cs); 890 TAILQ_FOREACH(cdw, &cs->cs_waiting_for_data_out, cdw_next) { 891 #if 0 892 CFISCSI_SESSION_DEBUG(cs, "have ttt 0x%x, itt 0x%x; looking for " 893 "ttt 0x%x, itt 0x%x", 894 bhsdo->bhsdo_target_transfer_tag, 895 bhsdo->bhsdo_initiator_task_tag, 896 cdw->cdw_target_transfer_tag, cdw->cdw_initiator_task_tag)); 897 #endif 898 if (bhsdo->bhsdo_target_transfer_tag == 899 cdw->cdw_target_transfer_tag) 900 break; 901 } 902 CFISCSI_SESSION_UNLOCK(cs); 903 if (cdw == NULL) { 904 CFISCSI_SESSION_WARN(cs, "data transfer tag 0x%x, initiator task tag " 905 "0x%x, not found; dropping connection", 906 bhsdo->bhsdo_target_transfer_tag, bhsdo->bhsdo_initiator_task_tag); 907 icl_pdu_free(request); 908 cfiscsi_session_terminate(cs); 909 return; 910 } 911 912 if (cdw->cdw_datasn != ntohl(bhsdo->bhsdo_datasn)) { 913 CFISCSI_SESSION_WARN(cs, "received Data-Out PDU with " 914 "DataSN %u, while expected %u; dropping connection", 915 ntohl(bhsdo->bhsdo_datasn), cdw->cdw_datasn); 916 icl_pdu_free(request); 917 cfiscsi_session_terminate(cs); 918 return; 919 } 920 cdw->cdw_datasn++; 921 922 io = cdw->cdw_ctl_io; 923 KASSERT((io->io_hdr.flags & CTL_FLAG_DATA_MASK) != CTL_FLAG_DATA_IN, 924 ("CTL_FLAG_DATA_IN")); 925 926 done = cfiscsi_handle_data_segment(request, cdw); 927 if (done) { 928 CFISCSI_SESSION_LOCK(cs); 929 TAILQ_REMOVE(&cs->cs_waiting_for_data_out, cdw, cdw_next); 930 CFISCSI_SESSION_UNLOCK(cs); 931 done = (io->scsiio.ext_data_filled != cdw->cdw_r2t_end || 932 io->scsiio.ext_data_filled == io->scsiio.kern_data_len); 933 cfiscsi_data_wait_free(cs, cdw); 934 if (done) 935 io->scsiio.be_move_done(io); 936 else 937 cfiscsi_datamove_out(io); 938 } 939 940 icl_pdu_free(request); 941 } 942 943 static void 944 cfiscsi_pdu_handle_logout_request(struct icl_pdu *request) 945 { 946 struct iscsi_bhs_logout_request *bhslr; 947 struct iscsi_bhs_logout_response *bhslr2; 948 struct icl_pdu *response; 949 struct cfiscsi_session *cs; 950 951 cs = PDU_SESSION(request); 952 bhslr = (struct iscsi_bhs_logout_request *)request->ip_bhs; 953 switch (bhslr->bhslr_reason & 0x7f) { 954 case BHSLR_REASON_CLOSE_SESSION: 955 case BHSLR_REASON_CLOSE_CONNECTION: 956 response = cfiscsi_pdu_new_response(request, M_NOWAIT); 957 if (response == NULL) { 958 CFISCSI_SESSION_DEBUG(cs, "failed to allocate memory"); 959 icl_pdu_free(request); 960 cfiscsi_session_terminate(cs); 961 return; 962 } 963 bhslr2 = (struct iscsi_bhs_logout_response *)response->ip_bhs; 964 bhslr2->bhslr_opcode = ISCSI_BHS_OPCODE_LOGOUT_RESPONSE; 965 bhslr2->bhslr_flags = 0x80; 966 bhslr2->bhslr_response = BHSLR_RESPONSE_CLOSED_SUCCESSFULLY; 967 bhslr2->bhslr_initiator_task_tag = 968 bhslr->bhslr_initiator_task_tag; 969 icl_pdu_free(request); 970 cfiscsi_pdu_queue(response); 971 cfiscsi_session_terminate(cs); 972 break; 973 case BHSLR_REASON_REMOVE_FOR_RECOVERY: 974 response = cfiscsi_pdu_new_response(request, M_NOWAIT); 975 if (response == NULL) { 976 CFISCSI_SESSION_WARN(cs, 977 "failed to allocate memory; dropping connection"); 978 icl_pdu_free(request); 979 cfiscsi_session_terminate(cs); 980 return; 981 } 982 bhslr2 = (struct iscsi_bhs_logout_response *)response->ip_bhs; 983 bhslr2->bhslr_opcode = ISCSI_BHS_OPCODE_LOGOUT_RESPONSE; 984 bhslr2->bhslr_flags = 0x80; 985 bhslr2->bhslr_response = BHSLR_RESPONSE_RECOVERY_NOT_SUPPORTED; 986 bhslr2->bhslr_initiator_task_tag = 987 bhslr->bhslr_initiator_task_tag; 988 icl_pdu_free(request); 989 cfiscsi_pdu_queue(response); 990 break; 991 default: 992 CFISCSI_SESSION_WARN(cs, "invalid reason 0%x; dropping connection", 993 bhslr->bhslr_reason); 994 icl_pdu_free(request); 995 cfiscsi_session_terminate(cs); 996 break; 997 } 998 } 999 1000 static void 1001 cfiscsi_callout(void *context) 1002 { 1003 struct icl_pdu *cp; 1004 struct iscsi_bhs_nop_in *bhsni; 1005 struct cfiscsi_session *cs; 1006 1007 cs = context; 1008 1009 if (cs->cs_terminating) 1010 return; 1011 1012 callout_schedule(&cs->cs_callout, 1 * hz); 1013 1014 atomic_add_int(&cs->cs_timeout, 1); 1015 1016 #ifdef ICL_KERNEL_PROXY 1017 if (cs->cs_waiting_for_ctld || cs->cs_login_phase) { 1018 if (login_timeout > 0 && cs->cs_timeout > login_timeout) { 1019 CFISCSI_SESSION_WARN(cs, "login timed out after " 1020 "%d seconds; dropping connection", cs->cs_timeout); 1021 cfiscsi_session_terminate(cs); 1022 } 1023 return; 1024 } 1025 #endif 1026 1027 if (ping_timeout <= 0) { 1028 /* 1029 * Pings are disabled. Don't send NOP-In in this case; 1030 * user might have disabled pings to work around problems 1031 * with certain initiators that can't properly handle 1032 * NOP-In, such as iPXE. Reset the timeout, to avoid 1033 * triggering reconnection, should the user decide to 1034 * reenable them. 1035 */ 1036 cs->cs_timeout = 0; 1037 return; 1038 } 1039 1040 if (cs->cs_timeout >= ping_timeout) { 1041 CFISCSI_SESSION_WARN(cs, "no ping reply (NOP-Out) after %d seconds; " 1042 "dropping connection", ping_timeout); 1043 cfiscsi_session_terminate(cs); 1044 return; 1045 } 1046 1047 /* 1048 * If the ping was reset less than one second ago - which means 1049 * that we've received some PDU during the last second - assume 1050 * the traffic flows correctly and don't bother sending a NOP-Out. 1051 * 1052 * (It's 2 - one for one second, and one for incrementing is_timeout 1053 * earlier in this routine.) 1054 */ 1055 if (cs->cs_timeout < 2) 1056 return; 1057 1058 cp = icl_pdu_new(cs->cs_conn, M_NOWAIT); 1059 if (cp == NULL) { 1060 CFISCSI_SESSION_WARN(cs, "failed to allocate memory"); 1061 return; 1062 } 1063 bhsni = (struct iscsi_bhs_nop_in *)cp->ip_bhs; 1064 bhsni->bhsni_opcode = ISCSI_BHS_OPCODE_NOP_IN; 1065 bhsni->bhsni_flags = 0x80; 1066 bhsni->bhsni_initiator_task_tag = 0xffffffff; 1067 1068 cfiscsi_pdu_queue(cp); 1069 } 1070 1071 static struct cfiscsi_data_wait * 1072 cfiscsi_data_wait_new(struct cfiscsi_session *cs, union ctl_io *io, 1073 uint32_t initiator_task_tag, uint32_t *target_transfer_tagp) 1074 { 1075 struct cfiscsi_data_wait *cdw; 1076 int error; 1077 1078 cdw = uma_zalloc(cfiscsi_data_wait_zone, M_NOWAIT | M_ZERO); 1079 if (cdw == NULL) { 1080 CFISCSI_SESSION_WARN(cs, 1081 "failed to allocate %zd bytes", sizeof(*cdw)); 1082 return (NULL); 1083 } 1084 1085 error = icl_conn_transfer_setup(cs->cs_conn, io, target_transfer_tagp, 1086 &cdw->cdw_icl_prv); 1087 if (error != 0) { 1088 CFISCSI_SESSION_WARN(cs, 1089 "icl_conn_transfer_setup() failed with error %d", error); 1090 uma_zfree(cfiscsi_data_wait_zone, cdw); 1091 return (NULL); 1092 } 1093 1094 cdw->cdw_ctl_io = io; 1095 cdw->cdw_target_transfer_tag = *target_transfer_tagp; 1096 cdw->cdw_initiator_task_tag = initiator_task_tag; 1097 1098 return (cdw); 1099 } 1100 1101 static void 1102 cfiscsi_data_wait_free(struct cfiscsi_session *cs, 1103 struct cfiscsi_data_wait *cdw) 1104 { 1105 1106 icl_conn_transfer_done(cs->cs_conn, cdw->cdw_icl_prv); 1107 uma_zfree(cfiscsi_data_wait_zone, cdw); 1108 } 1109 1110 static void 1111 cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs) 1112 { 1113 struct cfiscsi_data_wait *cdw; 1114 union ctl_io *io; 1115 int error, last, wait; 1116 1117 if (cs->cs_target == NULL) 1118 return; /* No target yet, so nothing to do. */ 1119 io = ctl_alloc_io(cs->cs_target->ct_port.ctl_pool_ref); 1120 ctl_zero_io(io); 1121 io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = cs; 1122 io->io_hdr.io_type = CTL_IO_TASK; 1123 io->io_hdr.nexus.initid.id = cs->cs_ctl_initid; 1124 io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port; 1125 io->io_hdr.nexus.targ_target.id = 0; 1126 io->io_hdr.nexus.targ_lun = 0; 1127 io->taskio.tag_type = CTL_TAG_SIMPLE; /* XXX */ 1128 io->taskio.task_action = CTL_TASK_I_T_NEXUS_RESET; 1129 wait = cs->cs_outstanding_ctl_pdus; 1130 refcount_acquire(&cs->cs_outstanding_ctl_pdus); 1131 error = ctl_queue(io); 1132 if (error != CTL_RETVAL_COMPLETE) { 1133 CFISCSI_SESSION_WARN(cs, "ctl_queue() failed; error %d", error); 1134 refcount_release(&cs->cs_outstanding_ctl_pdus); 1135 ctl_free_io(io); 1136 } 1137 1138 CFISCSI_SESSION_LOCK(cs); 1139 while ((cdw = TAILQ_FIRST(&cs->cs_waiting_for_data_out)) != NULL) { 1140 TAILQ_REMOVE(&cs->cs_waiting_for_data_out, cdw, cdw_next); 1141 CFISCSI_SESSION_UNLOCK(cs); 1142 /* 1143 * Set nonzero port status; this prevents backends from 1144 * assuming that the data transfer actually succeeded 1145 * and writing uninitialized data to disk. 1146 */ 1147 cdw->cdw_ctl_io->scsiio.io_hdr.port_status = 42; 1148 cdw->cdw_ctl_io->scsiio.be_move_done(cdw->cdw_ctl_io); 1149 cfiscsi_data_wait_free(cs, cdw); 1150 CFISCSI_SESSION_LOCK(cs); 1151 } 1152 CFISCSI_SESSION_UNLOCK(cs); 1153 1154 /* 1155 * Wait for CTL to terminate all the tasks. 1156 */ 1157 if (wait > 0) 1158 CFISCSI_SESSION_WARN(cs, 1159 "waiting for CTL to terminate %d tasks", wait); 1160 for (;;) { 1161 refcount_acquire(&cs->cs_outstanding_ctl_pdus); 1162 last = refcount_release(&cs->cs_outstanding_ctl_pdus); 1163 if (last != 0) 1164 break; 1165 tsleep(__DEVOLATILE(void *, &cs->cs_outstanding_ctl_pdus), 1166 0, "cfiscsi_terminate", hz / 100); 1167 } 1168 if (wait > 0) 1169 CFISCSI_SESSION_WARN(cs, "tasks terminated"); 1170 } 1171 1172 static void 1173 cfiscsi_maintenance_thread(void *arg) 1174 { 1175 struct cfiscsi_session *cs; 1176 1177 cs = arg; 1178 1179 for (;;) { 1180 CFISCSI_SESSION_LOCK(cs); 1181 if (cs->cs_terminating == false) 1182 cv_wait(&cs->cs_maintenance_cv, &cs->cs_lock); 1183 CFISCSI_SESSION_UNLOCK(cs); 1184 1185 if (cs->cs_terminating) { 1186 1187 /* 1188 * We used to wait up to 30 seconds to deliver queued 1189 * PDUs to the initiator. We also tried hard to deliver 1190 * SCSI Responses for the aborted PDUs. We don't do 1191 * that anymore. We might need to revisit that. 1192 */ 1193 callout_drain(&cs->cs_callout); 1194 icl_conn_close(cs->cs_conn); 1195 1196 /* 1197 * At this point ICL receive thread is no longer 1198 * running; no new tasks can be queued. 1199 */ 1200 cfiscsi_session_terminate_tasks(cs); 1201 cfiscsi_session_delete(cs); 1202 kthread_exit(); 1203 return; 1204 } 1205 CFISCSI_SESSION_DEBUG(cs, "nothing to do"); 1206 } 1207 } 1208 1209 static void 1210 cfiscsi_session_terminate(struct cfiscsi_session *cs) 1211 { 1212 1213 if (cs->cs_terminating) 1214 return; 1215 cs->cs_terminating = true; 1216 cv_signal(&cs->cs_maintenance_cv); 1217 #ifdef ICL_KERNEL_PROXY 1218 cv_signal(&cs->cs_login_cv); 1219 #endif 1220 } 1221 1222 static int 1223 cfiscsi_session_register_initiator(struct cfiscsi_session *cs) 1224 { 1225 struct cfiscsi_target *ct; 1226 char *name; 1227 int i; 1228 1229 KASSERT(cs->cs_ctl_initid == -1, ("already registered")); 1230 1231 ct = cs->cs_target; 1232 name = strdup(cs->cs_initiator_id, M_CTL); 1233 i = ctl_add_initiator(&ct->ct_port, -1, 0, name); 1234 if (i < 0) { 1235 CFISCSI_SESSION_WARN(cs, "ctl_add_initiator failed with error %d", 1236 i); 1237 cs->cs_ctl_initid = -1; 1238 return (1); 1239 } 1240 cs->cs_ctl_initid = i; 1241 #if 0 1242 CFISCSI_SESSION_DEBUG(cs, "added initiator id %d", i); 1243 #endif 1244 1245 return (0); 1246 } 1247 1248 static void 1249 cfiscsi_session_unregister_initiator(struct cfiscsi_session *cs) 1250 { 1251 int error; 1252 1253 if (cs->cs_ctl_initid == -1) 1254 return; 1255 1256 error = ctl_remove_initiator(&cs->cs_target->ct_port, cs->cs_ctl_initid); 1257 if (error != 0) { 1258 CFISCSI_SESSION_WARN(cs, "ctl_remove_initiator failed with error %d", 1259 error); 1260 } 1261 cs->cs_ctl_initid = -1; 1262 } 1263 1264 static struct cfiscsi_session * 1265 cfiscsi_session_new(struct cfiscsi_softc *softc, const char *offload) 1266 { 1267 struct cfiscsi_session *cs; 1268 int error; 1269 1270 cs = malloc(sizeof(*cs), M_CFISCSI, M_NOWAIT | M_ZERO); 1271 if (cs == NULL) { 1272 CFISCSI_WARN("malloc failed"); 1273 return (NULL); 1274 } 1275 cs->cs_ctl_initid = -1; 1276 1277 refcount_init(&cs->cs_outstanding_ctl_pdus, 0); 1278 TAILQ_INIT(&cs->cs_waiting_for_data_out); 1279 mtx_init(&cs->cs_lock, "cfiscsi_lock", NULL, MTX_DEF); 1280 cv_init(&cs->cs_maintenance_cv, "cfiscsi_mt"); 1281 #ifdef ICL_KERNEL_PROXY 1282 cv_init(&cs->cs_login_cv, "cfiscsi_login"); 1283 #endif 1284 1285 cs->cs_conn = icl_new_conn(offload, "cfiscsi", &cs->cs_lock); 1286 if (cs->cs_conn == NULL) { 1287 free(cs, M_CFISCSI); 1288 return (NULL); 1289 } 1290 cs->cs_conn->ic_receive = cfiscsi_receive_callback; 1291 cs->cs_conn->ic_error = cfiscsi_error_callback; 1292 cs->cs_conn->ic_prv0 = cs; 1293 1294 error = kthread_add(cfiscsi_maintenance_thread, cs, NULL, NULL, 0, 0, "cfiscsimt"); 1295 if (error != 0) { 1296 CFISCSI_SESSION_WARN(cs, "kthread_add(9) failed with error %d", error); 1297 free(cs, M_CFISCSI); 1298 return (NULL); 1299 } 1300 1301 mtx_lock(&softc->lock); 1302 cs->cs_id = ++softc->last_session_id; 1303 TAILQ_INSERT_TAIL(&softc->sessions, cs, cs_next); 1304 mtx_unlock(&softc->lock); 1305 1306 /* 1307 * Start pinging the initiator. 1308 */ 1309 callout_init(&cs->cs_callout, 1); 1310 callout_reset(&cs->cs_callout, 1 * hz, cfiscsi_callout, cs); 1311 1312 return (cs); 1313 } 1314 1315 static void 1316 cfiscsi_session_delete(struct cfiscsi_session *cs) 1317 { 1318 struct cfiscsi_softc *softc; 1319 1320 softc = &cfiscsi_softc; 1321 1322 KASSERT(cs->cs_outstanding_ctl_pdus == 0, 1323 ("destroying session with outstanding CTL pdus")); 1324 KASSERT(TAILQ_EMPTY(&cs->cs_waiting_for_data_out), 1325 ("destroying session with non-empty queue")); 1326 1327 cfiscsi_session_unregister_initiator(cs); 1328 if (cs->cs_target != NULL) 1329 cfiscsi_target_release(cs->cs_target); 1330 icl_conn_close(cs->cs_conn); 1331 icl_conn_free(cs->cs_conn); 1332 1333 mtx_lock(&softc->lock); 1334 TAILQ_REMOVE(&softc->sessions, cs, cs_next); 1335 cv_signal(&softc->sessions_cv); 1336 mtx_unlock(&softc->lock); 1337 1338 free(cs, M_CFISCSI); 1339 } 1340 1341 int 1342 cfiscsi_init(void) 1343 { 1344 struct cfiscsi_softc *softc; 1345 int retval; 1346 1347 softc = &cfiscsi_softc; 1348 retval = 0; 1349 bzero(softc, sizeof(*softc)); 1350 mtx_init(&softc->lock, "cfiscsi", NULL, MTX_DEF); 1351 1352 cv_init(&softc->sessions_cv, "cfiscsi_sessions"); 1353 #ifdef ICL_KERNEL_PROXY 1354 cv_init(&softc->accept_cv, "cfiscsi_accept"); 1355 #endif 1356 TAILQ_INIT(&softc->sessions); 1357 TAILQ_INIT(&softc->targets); 1358 1359 cfiscsi_data_wait_zone = uma_zcreate("cfiscsi_data_wait", 1360 sizeof(struct cfiscsi_data_wait), NULL, NULL, NULL, NULL, 1361 UMA_ALIGN_PTR, 0); 1362 1363 return (0); 1364 } 1365 1366 #ifdef ICL_KERNEL_PROXY 1367 static void 1368 cfiscsi_accept(struct socket *so, struct sockaddr *sa, int portal_id) 1369 { 1370 struct cfiscsi_session *cs; 1371 1372 cs = cfiscsi_session_new(&cfiscsi_softc, NULL); 1373 if (cs == NULL) { 1374 CFISCSI_WARN("failed to create session"); 1375 return; 1376 } 1377 1378 icl_conn_handoff_sock(cs->cs_conn, so); 1379 cs->cs_initiator_sa = sa; 1380 cs->cs_portal_id = portal_id; 1381 cs->cs_waiting_for_ctld = true; 1382 cv_signal(&cfiscsi_softc.accept_cv); 1383 } 1384 #endif 1385 1386 static void 1387 cfiscsi_online(void *arg) 1388 { 1389 struct cfiscsi_softc *softc; 1390 struct cfiscsi_target *ct; 1391 int online; 1392 1393 ct = (struct cfiscsi_target *)arg; 1394 softc = ct->ct_softc; 1395 1396 mtx_lock(&softc->lock); 1397 if (ct->ct_online) { 1398 mtx_unlock(&softc->lock); 1399 return; 1400 } 1401 ct->ct_online = 1; 1402 online = softc->online++; 1403 mtx_unlock(&softc->lock); 1404 if (online > 0) 1405 return; 1406 1407 #ifdef ICL_KERNEL_PROXY 1408 if (softc->listener != NULL) 1409 icl_listen_free(softc->listener); 1410 softc->listener = icl_listen_new(cfiscsi_accept); 1411 #endif 1412 } 1413 1414 static void 1415 cfiscsi_offline(void *arg) 1416 { 1417 struct cfiscsi_softc *softc; 1418 struct cfiscsi_target *ct; 1419 struct cfiscsi_session *cs; 1420 int online; 1421 1422 ct = (struct cfiscsi_target *)arg; 1423 softc = ct->ct_softc; 1424 1425 mtx_lock(&softc->lock); 1426 if (!ct->ct_online) { 1427 mtx_unlock(&softc->lock); 1428 return; 1429 } 1430 ct->ct_online = 0; 1431 online = --softc->online; 1432 1433 TAILQ_FOREACH(cs, &softc->sessions, cs_next) { 1434 if (cs->cs_target == ct) 1435 cfiscsi_session_terminate(cs); 1436 } 1437 do { 1438 TAILQ_FOREACH(cs, &softc->sessions, cs_next) { 1439 if (cs->cs_target == ct) 1440 break; 1441 } 1442 if (cs != NULL) 1443 cv_wait(&softc->sessions_cv, &softc->lock); 1444 } while (cs != NULL && ct->ct_online == 0); 1445 mtx_unlock(&softc->lock); 1446 if (online > 0) 1447 return; 1448 1449 #ifdef ICL_KERNEL_PROXY 1450 icl_listen_free(softc->listener); 1451 softc->listener = NULL; 1452 #endif 1453 } 1454 1455 static int 1456 cfiscsi_info(void *arg, struct sbuf *sb) 1457 { 1458 struct cfiscsi_target *ct = (struct cfiscsi_target *)arg; 1459 int retval; 1460 1461 retval = sbuf_printf(sb, "\t<cfiscsi_state>%d</cfiscsi_state>\n", 1462 ct->ct_state); 1463 return (retval); 1464 } 1465 1466 static void 1467 cfiscsi_ioctl_handoff(struct ctl_iscsi *ci) 1468 { 1469 struct cfiscsi_softc *softc; 1470 struct cfiscsi_session *cs, *cs2; 1471 struct cfiscsi_target *ct; 1472 struct ctl_iscsi_handoff_params *cihp; 1473 int error; 1474 1475 cihp = (struct ctl_iscsi_handoff_params *)&(ci->data); 1476 softc = &cfiscsi_softc; 1477 1478 CFISCSI_DEBUG("new connection from %s (%s) to %s", 1479 cihp->initiator_name, cihp->initiator_addr, 1480 cihp->target_name); 1481 1482 ct = cfiscsi_target_find(softc, cihp->target_name, 1483 cihp->portal_group_tag); 1484 if (ct == NULL) { 1485 ci->status = CTL_ISCSI_ERROR; 1486 snprintf(ci->error_str, sizeof(ci->error_str), 1487 "%s: target not found", __func__); 1488 return; 1489 } 1490 1491 #ifdef ICL_KERNEL_PROXY 1492 if (cihp->socket > 0 && cihp->connection_id > 0) { 1493 snprintf(ci->error_str, sizeof(ci->error_str), 1494 "both socket and connection_id set"); 1495 ci->status = CTL_ISCSI_ERROR; 1496 cfiscsi_target_release(ct); 1497 return; 1498 } 1499 if (cihp->socket == 0) { 1500 mtx_lock(&cfiscsi_softc.lock); 1501 TAILQ_FOREACH(cs, &cfiscsi_softc.sessions, cs_next) { 1502 if (cs->cs_id == cihp->connection_id) 1503 break; 1504 } 1505 if (cs == NULL) { 1506 mtx_unlock(&cfiscsi_softc.lock); 1507 snprintf(ci->error_str, sizeof(ci->error_str), 1508 "connection not found"); 1509 ci->status = CTL_ISCSI_ERROR; 1510 cfiscsi_target_release(ct); 1511 return; 1512 } 1513 mtx_unlock(&cfiscsi_softc.lock); 1514 } else { 1515 #endif 1516 cs = cfiscsi_session_new(softc, cihp->offload); 1517 if (cs == NULL) { 1518 ci->status = CTL_ISCSI_ERROR; 1519 snprintf(ci->error_str, sizeof(ci->error_str), 1520 "%s: cfiscsi_session_new failed", __func__); 1521 cfiscsi_target_release(ct); 1522 return; 1523 } 1524 #ifdef ICL_KERNEL_PROXY 1525 } 1526 #endif 1527 1528 /* 1529 * First PDU of Full Feature phase has the same CmdSN as the last 1530 * PDU from the Login Phase received from the initiator. Thus, 1531 * the -1 below. 1532 */ 1533 cs->cs_cmdsn = cihp->cmdsn; 1534 cs->cs_statsn = cihp->statsn; 1535 cs->cs_max_data_segment_length = cihp->max_recv_data_segment_length; 1536 cs->cs_max_burst_length = cihp->max_burst_length; 1537 cs->cs_immediate_data = !!cihp->immediate_data; 1538 if (cihp->header_digest == CTL_ISCSI_DIGEST_CRC32C) 1539 cs->cs_conn->ic_header_crc32c = true; 1540 if (cihp->data_digest == CTL_ISCSI_DIGEST_CRC32C) 1541 cs->cs_conn->ic_data_crc32c = true; 1542 1543 strlcpy(cs->cs_initiator_name, 1544 cihp->initiator_name, sizeof(cs->cs_initiator_name)); 1545 strlcpy(cs->cs_initiator_addr, 1546 cihp->initiator_addr, sizeof(cs->cs_initiator_addr)); 1547 strlcpy(cs->cs_initiator_alias, 1548 cihp->initiator_alias, sizeof(cs->cs_initiator_alias)); 1549 memcpy(cs->cs_initiator_isid, 1550 cihp->initiator_isid, sizeof(cs->cs_initiator_isid)); 1551 snprintf(cs->cs_initiator_id, sizeof(cs->cs_initiator_id), 1552 "%s,i,0x%02x%02x%02x%02x%02x%02x", cs->cs_initiator_name, 1553 cihp->initiator_isid[0], cihp->initiator_isid[1], 1554 cihp->initiator_isid[2], cihp->initiator_isid[3], 1555 cihp->initiator_isid[4], cihp->initiator_isid[5]); 1556 1557 mtx_lock(&softc->lock); 1558 if (ct->ct_online == 0) { 1559 mtx_unlock(&softc->lock); 1560 cfiscsi_session_terminate(cs); 1561 cfiscsi_target_release(ct); 1562 ci->status = CTL_ISCSI_ERROR; 1563 snprintf(ci->error_str, sizeof(ci->error_str), 1564 "%s: port offline", __func__); 1565 return; 1566 } 1567 cs->cs_target = ct; 1568 mtx_unlock(&softc->lock); 1569 1570 refcount_acquire(&cs->cs_outstanding_ctl_pdus); 1571 restart: 1572 if (!cs->cs_terminating) { 1573 mtx_lock(&softc->lock); 1574 TAILQ_FOREACH(cs2, &softc->sessions, cs_next) { 1575 if (cs2 != cs && cs2->cs_tasks_aborted == false && 1576 cs->cs_target == cs2->cs_target && 1577 strcmp(cs->cs_initiator_id, cs2->cs_initiator_id) == 0) { 1578 cfiscsi_session_terminate(cs2); 1579 mtx_unlock(&softc->lock); 1580 pause("cfiscsi_reinstate", 1); 1581 goto restart; 1582 } 1583 } 1584 mtx_unlock(&softc->lock); 1585 } 1586 1587 /* 1588 * Register initiator with CTL. 1589 */ 1590 cfiscsi_session_register_initiator(cs); 1591 1592 #ifdef ICL_KERNEL_PROXY 1593 if (cihp->socket > 0) { 1594 #endif 1595 error = icl_conn_handoff(cs->cs_conn, cihp->socket); 1596 if (error != 0) { 1597 cfiscsi_session_terminate(cs); 1598 refcount_release(&cs->cs_outstanding_ctl_pdus); 1599 ci->status = CTL_ISCSI_ERROR; 1600 snprintf(ci->error_str, sizeof(ci->error_str), 1601 "%s: icl_conn_handoff failed with error %d", 1602 __func__, error); 1603 return; 1604 } 1605 #ifdef ICL_KERNEL_PROXY 1606 } 1607 #endif 1608 1609 #ifdef ICL_KERNEL_PROXY 1610 cs->cs_login_phase = false; 1611 1612 /* 1613 * First PDU of the Full Feature phase has likely already arrived. 1614 * We have to pick it up and execute properly. 1615 */ 1616 if (cs->cs_login_pdu != NULL) { 1617 CFISCSI_SESSION_DEBUG(cs, "picking up first PDU"); 1618 cfiscsi_pdu_handle(cs->cs_login_pdu); 1619 cs->cs_login_pdu = NULL; 1620 } 1621 #endif 1622 1623 refcount_release(&cs->cs_outstanding_ctl_pdus); 1624 ci->status = CTL_ISCSI_OK; 1625 } 1626 1627 static void 1628 cfiscsi_ioctl_list(struct ctl_iscsi *ci) 1629 { 1630 struct ctl_iscsi_list_params *cilp; 1631 struct cfiscsi_session *cs; 1632 struct cfiscsi_softc *softc; 1633 struct sbuf *sb; 1634 int error; 1635 1636 cilp = (struct ctl_iscsi_list_params *)&(ci->data); 1637 softc = &cfiscsi_softc; 1638 1639 sb = sbuf_new(NULL, NULL, cilp->alloc_len, SBUF_FIXEDLEN); 1640 if (sb == NULL) { 1641 ci->status = CTL_ISCSI_ERROR; 1642 snprintf(ci->error_str, sizeof(ci->error_str), 1643 "Unable to allocate %d bytes for iSCSI session list", 1644 cilp->alloc_len); 1645 return; 1646 } 1647 1648 sbuf_printf(sb, "<ctlislist>\n"); 1649 mtx_lock(&softc->lock); 1650 TAILQ_FOREACH(cs, &softc->sessions, cs_next) { 1651 #ifdef ICL_KERNEL_PROXY 1652 if (cs->cs_target == NULL) 1653 continue; 1654 #endif 1655 error = sbuf_printf(sb, "<connection id=\"%d\">" 1656 "<initiator>%s</initiator>" 1657 "<initiator_addr>%s</initiator_addr>" 1658 "<initiator_alias>%s</initiator_alias>" 1659 "<target>%s</target>" 1660 "<target_alias>%s</target_alias>" 1661 "<target_portal_group_tag>%u</target_portal_group_tag>" 1662 "<header_digest>%s</header_digest>" 1663 "<data_digest>%s</data_digest>" 1664 "<max_data_segment_length>%zd</max_data_segment_length>" 1665 "<immediate_data>%d</immediate_data>" 1666 "<iser>%d</iser>" 1667 "<offload>%s</offload>" 1668 "</connection>\n", 1669 cs->cs_id, 1670 cs->cs_initiator_name, cs->cs_initiator_addr, cs->cs_initiator_alias, 1671 cs->cs_target->ct_name, cs->cs_target->ct_alias, 1672 cs->cs_target->ct_tag, 1673 cs->cs_conn->ic_header_crc32c ? "CRC32C" : "None", 1674 cs->cs_conn->ic_data_crc32c ? "CRC32C" : "None", 1675 cs->cs_max_data_segment_length, 1676 cs->cs_immediate_data, 1677 cs->cs_conn->ic_iser, 1678 cs->cs_conn->ic_offload); 1679 if (error != 0) 1680 break; 1681 } 1682 mtx_unlock(&softc->lock); 1683 error = sbuf_printf(sb, "</ctlislist>\n"); 1684 if (error != 0) { 1685 sbuf_delete(sb); 1686 ci->status = CTL_ISCSI_LIST_NEED_MORE_SPACE; 1687 snprintf(ci->error_str, sizeof(ci->error_str), 1688 "Out of space, %d bytes is too small", cilp->alloc_len); 1689 return; 1690 } 1691 sbuf_finish(sb); 1692 1693 error = copyout(sbuf_data(sb), cilp->conn_xml, sbuf_len(sb) + 1); 1694 cilp->fill_len = sbuf_len(sb) + 1; 1695 ci->status = CTL_ISCSI_OK; 1696 sbuf_delete(sb); 1697 } 1698 1699 static void 1700 cfiscsi_ioctl_logout(struct ctl_iscsi *ci) 1701 { 1702 struct icl_pdu *response; 1703 struct iscsi_bhs_asynchronous_message *bhsam; 1704 struct ctl_iscsi_logout_params *cilp; 1705 struct cfiscsi_session *cs; 1706 struct cfiscsi_softc *softc; 1707 int found = 0; 1708 1709 cilp = (struct ctl_iscsi_logout_params *)&(ci->data); 1710 softc = &cfiscsi_softc; 1711 1712 mtx_lock(&softc->lock); 1713 TAILQ_FOREACH(cs, &softc->sessions, cs_next) { 1714 if (cilp->all == 0 && cs->cs_id != cilp->connection_id && 1715 strcmp(cs->cs_initiator_name, cilp->initiator_name) != 0 && 1716 strcmp(cs->cs_initiator_addr, cilp->initiator_addr) != 0) 1717 continue; 1718 1719 response = icl_pdu_new(cs->cs_conn, M_NOWAIT); 1720 if (response == NULL) { 1721 ci->status = CTL_ISCSI_ERROR; 1722 snprintf(ci->error_str, sizeof(ci->error_str), 1723 "Unable to allocate memory"); 1724 mtx_unlock(&softc->lock); 1725 return; 1726 } 1727 bhsam = 1728 (struct iscsi_bhs_asynchronous_message *)response->ip_bhs; 1729 bhsam->bhsam_opcode = ISCSI_BHS_OPCODE_ASYNC_MESSAGE; 1730 bhsam->bhsam_flags = 0x80; 1731 bhsam->bhsam_async_event = BHSAM_EVENT_TARGET_REQUESTS_LOGOUT; 1732 bhsam->bhsam_parameter3 = htons(10); 1733 cfiscsi_pdu_queue(response); 1734 found++; 1735 } 1736 mtx_unlock(&softc->lock); 1737 1738 if (found == 0) { 1739 ci->status = CTL_ISCSI_SESSION_NOT_FOUND; 1740 snprintf(ci->error_str, sizeof(ci->error_str), 1741 "No matching connections found"); 1742 return; 1743 } 1744 1745 ci->status = CTL_ISCSI_OK; 1746 } 1747 1748 static void 1749 cfiscsi_ioctl_terminate(struct ctl_iscsi *ci) 1750 { 1751 struct icl_pdu *response; 1752 struct iscsi_bhs_asynchronous_message *bhsam; 1753 struct ctl_iscsi_terminate_params *citp; 1754 struct cfiscsi_session *cs; 1755 struct cfiscsi_softc *softc; 1756 int found = 0; 1757 1758 citp = (struct ctl_iscsi_terminate_params *)&(ci->data); 1759 softc = &cfiscsi_softc; 1760 1761 mtx_lock(&softc->lock); 1762 TAILQ_FOREACH(cs, &softc->sessions, cs_next) { 1763 if (citp->all == 0 && cs->cs_id != citp->connection_id && 1764 strcmp(cs->cs_initiator_name, citp->initiator_name) != 0 && 1765 strcmp(cs->cs_initiator_addr, citp->initiator_addr) != 0) 1766 continue; 1767 1768 response = icl_pdu_new(cs->cs_conn, M_NOWAIT); 1769 if (response == NULL) { 1770 /* 1771 * Oh well. Just terminate the connection. 1772 */ 1773 } else { 1774 bhsam = (struct iscsi_bhs_asynchronous_message *) 1775 response->ip_bhs; 1776 bhsam->bhsam_opcode = ISCSI_BHS_OPCODE_ASYNC_MESSAGE; 1777 bhsam->bhsam_flags = 0x80; 1778 bhsam->bhsam_0xffffffff = 0xffffffff; 1779 bhsam->bhsam_async_event = 1780 BHSAM_EVENT_TARGET_TERMINATES_SESSION; 1781 cfiscsi_pdu_queue(response); 1782 } 1783 cfiscsi_session_terminate(cs); 1784 found++; 1785 } 1786 mtx_unlock(&softc->lock); 1787 1788 if (found == 0) { 1789 ci->status = CTL_ISCSI_SESSION_NOT_FOUND; 1790 snprintf(ci->error_str, sizeof(ci->error_str), 1791 "No matching connections found"); 1792 return; 1793 } 1794 1795 ci->status = CTL_ISCSI_OK; 1796 } 1797 1798 static void 1799 cfiscsi_ioctl_limits(struct ctl_iscsi *ci) 1800 { 1801 struct ctl_iscsi_limits_params *cilp; 1802 int error; 1803 1804 cilp = (struct ctl_iscsi_limits_params *)&(ci->data); 1805 1806 error = icl_limits(cilp->offload, &cilp->data_segment_limit); 1807 if (error != 0) { 1808 ci->status = CTL_ISCSI_ERROR; 1809 snprintf(ci->error_str, sizeof(ci->error_str), 1810 "%s: icl_limits failed with error %d", 1811 __func__, error); 1812 return; 1813 } 1814 1815 ci->status = CTL_ISCSI_OK; 1816 } 1817 1818 #ifdef ICL_KERNEL_PROXY 1819 static void 1820 cfiscsi_ioctl_listen(struct ctl_iscsi *ci) 1821 { 1822 struct ctl_iscsi_listen_params *cilp; 1823 struct sockaddr *sa; 1824 int error; 1825 1826 cilp = (struct ctl_iscsi_listen_params *)&(ci->data); 1827 1828 if (cfiscsi_softc.listener == NULL) { 1829 CFISCSI_DEBUG("no listener"); 1830 snprintf(ci->error_str, sizeof(ci->error_str), "no listener"); 1831 ci->status = CTL_ISCSI_ERROR; 1832 return; 1833 } 1834 1835 error = getsockaddr(&sa, (void *)cilp->addr, cilp->addrlen); 1836 if (error != 0) { 1837 CFISCSI_DEBUG("getsockaddr, error %d", error); 1838 snprintf(ci->error_str, sizeof(ci->error_str), "getsockaddr failed"); 1839 ci->status = CTL_ISCSI_ERROR; 1840 return; 1841 } 1842 1843 error = icl_listen_add(cfiscsi_softc.listener, cilp->iser, cilp->domain, 1844 cilp->socktype, cilp->protocol, sa, cilp->portal_id); 1845 if (error != 0) { 1846 free(sa, M_SONAME); 1847 CFISCSI_DEBUG("icl_listen_add, error %d", error); 1848 snprintf(ci->error_str, sizeof(ci->error_str), 1849 "icl_listen_add failed, error %d", error); 1850 ci->status = CTL_ISCSI_ERROR; 1851 return; 1852 } 1853 1854 ci->status = CTL_ISCSI_OK; 1855 } 1856 1857 static void 1858 cfiscsi_ioctl_accept(struct ctl_iscsi *ci) 1859 { 1860 struct ctl_iscsi_accept_params *ciap; 1861 struct cfiscsi_session *cs; 1862 int error; 1863 1864 ciap = (struct ctl_iscsi_accept_params *)&(ci->data); 1865 1866 mtx_lock(&cfiscsi_softc.lock); 1867 for (;;) { 1868 TAILQ_FOREACH(cs, &cfiscsi_softc.sessions, cs_next) { 1869 if (cs->cs_waiting_for_ctld) 1870 break; 1871 } 1872 if (cs != NULL) 1873 break; 1874 error = cv_wait_sig(&cfiscsi_softc.accept_cv, &cfiscsi_softc.lock); 1875 if (error != 0) { 1876 mtx_unlock(&cfiscsi_softc.lock); 1877 snprintf(ci->error_str, sizeof(ci->error_str), "interrupted"); 1878 ci->status = CTL_ISCSI_ERROR; 1879 return; 1880 } 1881 } 1882 mtx_unlock(&cfiscsi_softc.lock); 1883 1884 cs->cs_waiting_for_ctld = false; 1885 cs->cs_login_phase = true; 1886 1887 ciap->connection_id = cs->cs_id; 1888 ciap->portal_id = cs->cs_portal_id; 1889 ciap->initiator_addrlen = cs->cs_initiator_sa->sa_len; 1890 error = copyout(cs->cs_initiator_sa, ciap->initiator_addr, 1891 cs->cs_initiator_sa->sa_len); 1892 if (error != 0) { 1893 snprintf(ci->error_str, sizeof(ci->error_str), 1894 "copyout failed with error %d", error); 1895 ci->status = CTL_ISCSI_ERROR; 1896 return; 1897 } 1898 1899 ci->status = CTL_ISCSI_OK; 1900 } 1901 1902 static void 1903 cfiscsi_ioctl_send(struct ctl_iscsi *ci) 1904 { 1905 struct ctl_iscsi_send_params *cisp; 1906 struct cfiscsi_session *cs; 1907 struct icl_pdu *ip; 1908 size_t datalen; 1909 void *data; 1910 int error; 1911 1912 cisp = (struct ctl_iscsi_send_params *)&(ci->data); 1913 1914 mtx_lock(&cfiscsi_softc.lock); 1915 TAILQ_FOREACH(cs, &cfiscsi_softc.sessions, cs_next) { 1916 if (cs->cs_id == cisp->connection_id) 1917 break; 1918 } 1919 if (cs == NULL) { 1920 mtx_unlock(&cfiscsi_softc.lock); 1921 snprintf(ci->error_str, sizeof(ci->error_str), "connection not found"); 1922 ci->status = CTL_ISCSI_ERROR; 1923 return; 1924 } 1925 mtx_unlock(&cfiscsi_softc.lock); 1926 1927 #if 0 1928 if (cs->cs_login_phase == false) 1929 return (EBUSY); 1930 #endif 1931 1932 if (cs->cs_terminating) { 1933 snprintf(ci->error_str, sizeof(ci->error_str), "connection is terminating"); 1934 ci->status = CTL_ISCSI_ERROR; 1935 return; 1936 } 1937 1938 datalen = cisp->data_segment_len; 1939 /* 1940 * XXX 1941 */ 1942 //if (datalen > CFISCSI_MAX_DATA_SEGMENT_LENGTH) { 1943 if (datalen > 65535) { 1944 snprintf(ci->error_str, sizeof(ci->error_str), "data segment too big"); 1945 ci->status = CTL_ISCSI_ERROR; 1946 return; 1947 } 1948 if (datalen > 0) { 1949 data = malloc(datalen, M_CFISCSI, M_WAITOK); 1950 error = copyin(cisp->data_segment, data, datalen); 1951 if (error != 0) { 1952 free(data, M_CFISCSI); 1953 snprintf(ci->error_str, sizeof(ci->error_str), "copyin error %d", error); 1954 ci->status = CTL_ISCSI_ERROR; 1955 return; 1956 } 1957 } 1958 1959 ip = icl_pdu_new(cs->cs_conn, M_WAITOK); 1960 memcpy(ip->ip_bhs, cisp->bhs, sizeof(*ip->ip_bhs)); 1961 if (datalen > 0) { 1962 icl_pdu_append_data(ip, data, datalen, M_WAITOK); 1963 free(data, M_CFISCSI); 1964 } 1965 CFISCSI_SESSION_LOCK(cs); 1966 icl_pdu_queue(ip); 1967 CFISCSI_SESSION_UNLOCK(cs); 1968 ci->status = CTL_ISCSI_OK; 1969 } 1970 1971 static void 1972 cfiscsi_ioctl_receive(struct ctl_iscsi *ci) 1973 { 1974 struct ctl_iscsi_receive_params *cirp; 1975 struct cfiscsi_session *cs; 1976 struct icl_pdu *ip; 1977 void *data; 1978 int error; 1979 1980 cirp = (struct ctl_iscsi_receive_params *)&(ci->data); 1981 1982 mtx_lock(&cfiscsi_softc.lock); 1983 TAILQ_FOREACH(cs, &cfiscsi_softc.sessions, cs_next) { 1984 if (cs->cs_id == cirp->connection_id) 1985 break; 1986 } 1987 if (cs == NULL) { 1988 mtx_unlock(&cfiscsi_softc.lock); 1989 snprintf(ci->error_str, sizeof(ci->error_str), 1990 "connection not found"); 1991 ci->status = CTL_ISCSI_ERROR; 1992 return; 1993 } 1994 mtx_unlock(&cfiscsi_softc.lock); 1995 1996 #if 0 1997 if (is->is_login_phase == false) 1998 return (EBUSY); 1999 #endif 2000 2001 CFISCSI_SESSION_LOCK(cs); 2002 while (cs->cs_login_pdu == NULL && cs->cs_terminating == false) { 2003 error = cv_wait_sig(&cs->cs_login_cv, &cs->cs_lock); 2004 if (error != 0) { 2005 CFISCSI_SESSION_UNLOCK(cs); 2006 snprintf(ci->error_str, sizeof(ci->error_str), 2007 "interrupted by signal"); 2008 ci->status = CTL_ISCSI_ERROR; 2009 return; 2010 } 2011 } 2012 2013 if (cs->cs_terminating) { 2014 CFISCSI_SESSION_UNLOCK(cs); 2015 snprintf(ci->error_str, sizeof(ci->error_str), 2016 "connection terminating"); 2017 ci->status = CTL_ISCSI_ERROR; 2018 return; 2019 } 2020 ip = cs->cs_login_pdu; 2021 cs->cs_login_pdu = NULL; 2022 CFISCSI_SESSION_UNLOCK(cs); 2023 2024 if (ip->ip_data_len > cirp->data_segment_len) { 2025 icl_pdu_free(ip); 2026 snprintf(ci->error_str, sizeof(ci->error_str), 2027 "data segment too big"); 2028 ci->status = CTL_ISCSI_ERROR; 2029 return; 2030 } 2031 2032 copyout(ip->ip_bhs, cirp->bhs, sizeof(*ip->ip_bhs)); 2033 if (ip->ip_data_len > 0) { 2034 data = malloc(ip->ip_data_len, M_CFISCSI, M_WAITOK); 2035 icl_pdu_get_data(ip, 0, data, ip->ip_data_len); 2036 copyout(data, cirp->data_segment, ip->ip_data_len); 2037 free(data, M_CFISCSI); 2038 } 2039 2040 icl_pdu_free(ip); 2041 ci->status = CTL_ISCSI_OK; 2042 } 2043 2044 #endif /* !ICL_KERNEL_PROXY */ 2045 2046 static void 2047 cfiscsi_ioctl_port_create(struct ctl_req *req) 2048 { 2049 struct cfiscsi_target *ct; 2050 struct ctl_port *port; 2051 const char *target, *alias, *tags; 2052 struct scsi_vpd_id_descriptor *desc; 2053 ctl_options_t opts; 2054 int retval, len, idlen; 2055 uint16_t tag; 2056 2057 ctl_init_opts(&opts, req->num_args, req->kern_args); 2058 target = ctl_get_opt(&opts, "cfiscsi_target"); 2059 alias = ctl_get_opt(&opts, "cfiscsi_target_alias"); 2060 tags = ctl_get_opt(&opts, "cfiscsi_portal_group_tag"); 2061 if (target == NULL || tags == NULL) { 2062 req->status = CTL_LUN_ERROR; 2063 snprintf(req->error_str, sizeof(req->error_str), 2064 "Missing required argument"); 2065 ctl_free_opts(&opts); 2066 return; 2067 } 2068 tag = strtol(tags, (char **)NULL, 10); 2069 ct = cfiscsi_target_find_or_create(&cfiscsi_softc, target, alias, tag); 2070 if (ct == NULL) { 2071 req->status = CTL_LUN_ERROR; 2072 snprintf(req->error_str, sizeof(req->error_str), 2073 "failed to create target \"%s\"", target); 2074 ctl_free_opts(&opts); 2075 return; 2076 } 2077 if (ct->ct_state == CFISCSI_TARGET_STATE_ACTIVE) { 2078 req->status = CTL_LUN_ERROR; 2079 snprintf(req->error_str, sizeof(req->error_str), 2080 "target \"%s\" already exists", target); 2081 cfiscsi_target_release(ct); 2082 ctl_free_opts(&opts); 2083 return; 2084 } 2085 port = &ct->ct_port; 2086 // WAT 2087 if (ct->ct_state == CFISCSI_TARGET_STATE_DYING) 2088 goto done; 2089 2090 port->frontend = &cfiscsi_frontend; 2091 port->port_type = CTL_PORT_ISCSI; 2092 /* XXX KDM what should the real number be here? */ 2093 port->num_requested_ctl_io = 4096; 2094 port->port_name = "iscsi"; 2095 port->physical_port = tag; 2096 port->virtual_port = ct->ct_target_id; 2097 port->port_online = cfiscsi_online; 2098 port->port_offline = cfiscsi_offline; 2099 port->port_info = cfiscsi_info; 2100 port->onoff_arg = ct; 2101 port->fe_datamove = cfiscsi_datamove; 2102 port->fe_done = cfiscsi_done; 2103 2104 /* XXX KDM what should we report here? */ 2105 /* XXX These should probably be fetched from CTL. */ 2106 port->max_targets = 1; 2107 port->max_target_id = 15; 2108 2109 port->options = opts; 2110 STAILQ_INIT(&opts); 2111 2112 /* Generate Port ID. */ 2113 idlen = strlen(target) + strlen(",t,0x0001") + 1; 2114 idlen = roundup2(idlen, 4); 2115 len = sizeof(struct scsi_vpd_device_id) + idlen; 2116 port->port_devid = malloc(sizeof(struct ctl_devid) + len, 2117 M_CTL, M_WAITOK | M_ZERO); 2118 port->port_devid->len = len; 2119 desc = (struct scsi_vpd_id_descriptor *)port->port_devid->data; 2120 desc->proto_codeset = (SCSI_PROTO_ISCSI << 4) | SVPD_ID_CODESET_UTF8; 2121 desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT | 2122 SVPD_ID_TYPE_SCSI_NAME; 2123 desc->length = idlen; 2124 snprintf(desc->identifier, idlen, "%s,t,0x%4.4x", target, tag); 2125 2126 /* Generate Target ID. */ 2127 idlen = strlen(target) + 1; 2128 idlen = roundup2(idlen, 4); 2129 len = sizeof(struct scsi_vpd_device_id) + idlen; 2130 port->target_devid = malloc(sizeof(struct ctl_devid) + len, 2131 M_CTL, M_WAITOK | M_ZERO); 2132 port->target_devid->len = len; 2133 desc = (struct scsi_vpd_id_descriptor *)port->target_devid->data; 2134 desc->proto_codeset = (SCSI_PROTO_ISCSI << 4) | SVPD_ID_CODESET_UTF8; 2135 desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_TARGET | 2136 SVPD_ID_TYPE_SCSI_NAME; 2137 desc->length = idlen; 2138 strlcpy(desc->identifier, target, idlen); 2139 2140 retval = ctl_port_register(port); 2141 if (retval != 0) { 2142 ctl_free_opts(&port->options); 2143 cfiscsi_target_release(ct); 2144 free(port->port_devid, M_CFISCSI); 2145 free(port->target_devid, M_CFISCSI); 2146 req->status = CTL_LUN_ERROR; 2147 snprintf(req->error_str, sizeof(req->error_str), 2148 "ctl_port_register() failed with error %d", retval); 2149 return; 2150 } 2151 done: 2152 ct->ct_state = CFISCSI_TARGET_STATE_ACTIVE; 2153 req->status = CTL_LUN_OK; 2154 memcpy(req->kern_args[0].kvalue, &port->targ_port, 2155 sizeof(port->targ_port)); //XXX 2156 } 2157 2158 static void 2159 cfiscsi_ioctl_port_remove(struct ctl_req *req) 2160 { 2161 struct cfiscsi_target *ct; 2162 const char *target, *tags; 2163 ctl_options_t opts; 2164 uint16_t tag; 2165 2166 ctl_init_opts(&opts, req->num_args, req->kern_args); 2167 target = ctl_get_opt(&opts, "cfiscsi_target"); 2168 tags = ctl_get_opt(&opts, "cfiscsi_portal_group_tag"); 2169 if (target == NULL || tags == NULL) { 2170 ctl_free_opts(&opts); 2171 req->status = CTL_LUN_ERROR; 2172 snprintf(req->error_str, sizeof(req->error_str), 2173 "Missing required argument"); 2174 return; 2175 } 2176 tag = strtol(tags, (char **)NULL, 10); 2177 ct = cfiscsi_target_find(&cfiscsi_softc, target, tag); 2178 if (ct == NULL) { 2179 ctl_free_opts(&opts); 2180 req->status = CTL_LUN_ERROR; 2181 snprintf(req->error_str, sizeof(req->error_str), 2182 "can't find target \"%s\"", target); 2183 return; 2184 } 2185 if (ct->ct_state != CFISCSI_TARGET_STATE_ACTIVE) { 2186 ctl_free_opts(&opts); 2187 req->status = CTL_LUN_ERROR; 2188 snprintf(req->error_str, sizeof(req->error_str), 2189 "target \"%s\" is already dying", target); 2190 return; 2191 } 2192 ctl_free_opts(&opts); 2193 2194 ct->ct_state = CFISCSI_TARGET_STATE_DYING; 2195 ctl_port_offline(&ct->ct_port); 2196 cfiscsi_target_release(ct); 2197 cfiscsi_target_release(ct); 2198 req->status = CTL_LUN_OK; 2199 } 2200 2201 static int 2202 cfiscsi_ioctl(struct cdev *dev, 2203 u_long cmd, caddr_t addr, int flag, struct thread *td) 2204 { 2205 struct ctl_iscsi *ci; 2206 struct ctl_req *req; 2207 2208 if (cmd == CTL_PORT_REQ) { 2209 req = (struct ctl_req *)addr; 2210 switch (req->reqtype) { 2211 case CTL_REQ_CREATE: 2212 cfiscsi_ioctl_port_create(req); 2213 break; 2214 case CTL_REQ_REMOVE: 2215 cfiscsi_ioctl_port_remove(req); 2216 break; 2217 default: 2218 req->status = CTL_LUN_ERROR; 2219 snprintf(req->error_str, sizeof(req->error_str), 2220 "Unsupported request type %d", req->reqtype); 2221 } 2222 return (0); 2223 } 2224 2225 if (cmd != CTL_ISCSI) 2226 return (ENOTTY); 2227 2228 ci = (struct ctl_iscsi *)addr; 2229 switch (ci->type) { 2230 case CTL_ISCSI_HANDOFF: 2231 cfiscsi_ioctl_handoff(ci); 2232 break; 2233 case CTL_ISCSI_LIST: 2234 cfiscsi_ioctl_list(ci); 2235 break; 2236 case CTL_ISCSI_LOGOUT: 2237 cfiscsi_ioctl_logout(ci); 2238 break; 2239 case CTL_ISCSI_TERMINATE: 2240 cfiscsi_ioctl_terminate(ci); 2241 break; 2242 case CTL_ISCSI_LIMITS: 2243 cfiscsi_ioctl_limits(ci); 2244 break; 2245 #ifdef ICL_KERNEL_PROXY 2246 case CTL_ISCSI_LISTEN: 2247 cfiscsi_ioctl_listen(ci); 2248 break; 2249 case CTL_ISCSI_ACCEPT: 2250 cfiscsi_ioctl_accept(ci); 2251 break; 2252 case CTL_ISCSI_SEND: 2253 cfiscsi_ioctl_send(ci); 2254 break; 2255 case CTL_ISCSI_RECEIVE: 2256 cfiscsi_ioctl_receive(ci); 2257 break; 2258 #else 2259 case CTL_ISCSI_LISTEN: 2260 case CTL_ISCSI_ACCEPT: 2261 case CTL_ISCSI_SEND: 2262 case CTL_ISCSI_RECEIVE: 2263 ci->status = CTL_ISCSI_ERROR; 2264 snprintf(ci->error_str, sizeof(ci->error_str), 2265 "%s: CTL compiled without ICL_KERNEL_PROXY", 2266 __func__); 2267 break; 2268 #endif /* !ICL_KERNEL_PROXY */ 2269 default: 2270 ci->status = CTL_ISCSI_ERROR; 2271 snprintf(ci->error_str, sizeof(ci->error_str), 2272 "%s: invalid iSCSI request type %d", __func__, ci->type); 2273 break; 2274 } 2275 2276 return (0); 2277 } 2278 2279 static void 2280 cfiscsi_target_hold(struct cfiscsi_target *ct) 2281 { 2282 2283 refcount_acquire(&ct->ct_refcount); 2284 } 2285 2286 static void 2287 cfiscsi_target_release(struct cfiscsi_target *ct) 2288 { 2289 struct cfiscsi_softc *softc; 2290 2291 softc = ct->ct_softc; 2292 mtx_lock(&softc->lock); 2293 if (refcount_release(&ct->ct_refcount)) { 2294 TAILQ_REMOVE(&softc->targets, ct, ct_next); 2295 mtx_unlock(&softc->lock); 2296 if (ct->ct_state != CFISCSI_TARGET_STATE_INVALID) { 2297 ct->ct_state = CFISCSI_TARGET_STATE_INVALID; 2298 if (ctl_port_deregister(&ct->ct_port) != 0) 2299 printf("%s: ctl_port_deregister() failed\n", 2300 __func__); 2301 } 2302 free(ct, M_CFISCSI); 2303 2304 return; 2305 } 2306 mtx_unlock(&softc->lock); 2307 } 2308 2309 static struct cfiscsi_target * 2310 cfiscsi_target_find(struct cfiscsi_softc *softc, const char *name, uint16_t tag) 2311 { 2312 struct cfiscsi_target *ct; 2313 2314 mtx_lock(&softc->lock); 2315 TAILQ_FOREACH(ct, &softc->targets, ct_next) { 2316 if (ct->ct_tag != tag || 2317 strcmp(name, ct->ct_name) != 0 || 2318 ct->ct_state != CFISCSI_TARGET_STATE_ACTIVE) 2319 continue; 2320 cfiscsi_target_hold(ct); 2321 mtx_unlock(&softc->lock); 2322 return (ct); 2323 } 2324 mtx_unlock(&softc->lock); 2325 2326 return (NULL); 2327 } 2328 2329 static struct cfiscsi_target * 2330 cfiscsi_target_find_or_create(struct cfiscsi_softc *softc, const char *name, 2331 const char *alias, uint16_t tag) 2332 { 2333 struct cfiscsi_target *ct, *newct; 2334 2335 if (name[0] == '\0' || strlen(name) >= CTL_ISCSI_NAME_LEN) 2336 return (NULL); 2337 2338 newct = malloc(sizeof(*newct), M_CFISCSI, M_WAITOK | M_ZERO); 2339 2340 mtx_lock(&softc->lock); 2341 TAILQ_FOREACH(ct, &softc->targets, ct_next) { 2342 if (ct->ct_tag != tag || 2343 strcmp(name, ct->ct_name) != 0 || 2344 ct->ct_state == CFISCSI_TARGET_STATE_INVALID) 2345 continue; 2346 cfiscsi_target_hold(ct); 2347 mtx_unlock(&softc->lock); 2348 free(newct, M_CFISCSI); 2349 return (ct); 2350 } 2351 2352 strlcpy(newct->ct_name, name, sizeof(newct->ct_name)); 2353 if (alias != NULL) 2354 strlcpy(newct->ct_alias, alias, sizeof(newct->ct_alias)); 2355 newct->ct_tag = tag; 2356 refcount_init(&newct->ct_refcount, 1); 2357 newct->ct_softc = softc; 2358 if (TAILQ_EMPTY(&softc->targets)) 2359 softc->last_target_id = 0; 2360 newct->ct_target_id = ++softc->last_target_id; 2361 TAILQ_INSERT_TAIL(&softc->targets, newct, ct_next); 2362 mtx_unlock(&softc->lock); 2363 2364 return (newct); 2365 } 2366 2367 static void 2368 cfiscsi_datamove_in(union ctl_io *io) 2369 { 2370 struct cfiscsi_session *cs; 2371 struct icl_pdu *request, *response; 2372 const struct iscsi_bhs_scsi_command *bhssc; 2373 struct iscsi_bhs_data_in *bhsdi; 2374 struct ctl_sg_entry ctl_sg_entry, *ctl_sglist; 2375 size_t len, expected_len, sg_len, buffer_offset; 2376 const char *sg_addr; 2377 int ctl_sg_count, error, i; 2378 2379 request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 2380 cs = PDU_SESSION(request); 2381 2382 bhssc = (const struct iscsi_bhs_scsi_command *)request->ip_bhs; 2383 KASSERT((bhssc->bhssc_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) == 2384 ISCSI_BHS_OPCODE_SCSI_COMMAND, 2385 ("bhssc->bhssc_opcode != ISCSI_BHS_OPCODE_SCSI_COMMAND")); 2386 2387 if (io->scsiio.kern_sg_entries > 0) { 2388 ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr; 2389 ctl_sg_count = io->scsiio.kern_sg_entries; 2390 } else { 2391 ctl_sglist = &ctl_sg_entry; 2392 ctl_sglist->addr = io->scsiio.kern_data_ptr; 2393 ctl_sglist->len = io->scsiio.kern_data_len; 2394 ctl_sg_count = 1; 2395 } 2396 2397 /* 2398 * This is the total amount of data to be transferred within the current 2399 * SCSI command. We need to record it so that we can properly report 2400 * underflow/underflow. 2401 */ 2402 PDU_TOTAL_TRANSFER_LEN(request) = io->scsiio.kern_total_len; 2403 2404 /* 2405 * This is the offset within the current SCSI command; for the first 2406 * call to cfiscsi_datamove() it will be 0, and for subsequent ones 2407 * it will be the sum of lengths of previous ones. 2408 */ 2409 buffer_offset = io->scsiio.kern_rel_offset; 2410 2411 /* 2412 * This is the transfer length expected by the initiator. In theory, 2413 * it could be different from the correct amount of data from the SCSI 2414 * point of view, even if that doesn't make any sense. 2415 */ 2416 expected_len = ntohl(bhssc->bhssc_expected_data_transfer_length); 2417 #if 0 2418 if (expected_len != io->scsiio.kern_total_len) { 2419 CFISCSI_SESSION_DEBUG(cs, "expected transfer length %zd, " 2420 "actual length %zd", expected_len, 2421 (size_t)io->scsiio.kern_total_len); 2422 } 2423 #endif 2424 2425 if (buffer_offset >= expected_len) { 2426 #if 0 2427 CFISCSI_SESSION_DEBUG(cs, "buffer_offset = %zd, " 2428 "already sent the expected len", buffer_offset); 2429 #endif 2430 io->scsiio.be_move_done(io); 2431 return; 2432 } 2433 2434 i = 0; 2435 sg_addr = NULL; 2436 sg_len = 0; 2437 response = NULL; 2438 bhsdi = NULL; 2439 for (;;) { 2440 if (response == NULL) { 2441 response = cfiscsi_pdu_new_response(request, M_NOWAIT); 2442 if (response == NULL) { 2443 CFISCSI_SESSION_WARN(cs, "failed to " 2444 "allocate memory; dropping connection"); 2445 ctl_set_busy(&io->scsiio); 2446 io->scsiio.be_move_done(io); 2447 cfiscsi_session_terminate(cs); 2448 return; 2449 } 2450 bhsdi = (struct iscsi_bhs_data_in *)response->ip_bhs; 2451 bhsdi->bhsdi_opcode = ISCSI_BHS_OPCODE_SCSI_DATA_IN; 2452 bhsdi->bhsdi_initiator_task_tag = 2453 bhssc->bhssc_initiator_task_tag; 2454 bhsdi->bhsdi_datasn = htonl(PDU_EXPDATASN(request)); 2455 PDU_EXPDATASN(request)++; 2456 bhsdi->bhsdi_buffer_offset = htonl(buffer_offset); 2457 } 2458 2459 KASSERT(i < ctl_sg_count, ("i >= ctl_sg_count")); 2460 if (sg_len == 0) { 2461 sg_addr = ctl_sglist[i].addr; 2462 sg_len = ctl_sglist[i].len; 2463 KASSERT(sg_len > 0, ("sg_len <= 0")); 2464 } 2465 2466 len = sg_len; 2467 2468 /* 2469 * Truncate to maximum data segment length. 2470 */ 2471 KASSERT(response->ip_data_len < cs->cs_max_data_segment_length, 2472 ("ip_data_len %zd >= max_data_segment_length %zd", 2473 response->ip_data_len, cs->cs_max_data_segment_length)); 2474 if (response->ip_data_len + len > 2475 cs->cs_max_data_segment_length) { 2476 len = cs->cs_max_data_segment_length - 2477 response->ip_data_len; 2478 KASSERT(len <= sg_len, ("len %zd > sg_len %zd", 2479 len, sg_len)); 2480 } 2481 2482 /* 2483 * Truncate to expected data transfer length. 2484 */ 2485 KASSERT(buffer_offset + response->ip_data_len < expected_len, 2486 ("buffer_offset %zd + ip_data_len %zd >= expected_len %zd", 2487 buffer_offset, response->ip_data_len, expected_len)); 2488 if (buffer_offset + response->ip_data_len + len > expected_len) { 2489 CFISCSI_SESSION_DEBUG(cs, "truncating from %zd " 2490 "to expected data transfer length %zd", 2491 buffer_offset + response->ip_data_len + len, expected_len); 2492 len = expected_len - (buffer_offset + response->ip_data_len); 2493 KASSERT(len <= sg_len, ("len %zd > sg_len %zd", 2494 len, sg_len)); 2495 } 2496 2497 error = icl_pdu_append_data(response, sg_addr, len, M_NOWAIT); 2498 if (error != 0) { 2499 CFISCSI_SESSION_WARN(cs, "failed to " 2500 "allocate memory; dropping connection"); 2501 icl_pdu_free(response); 2502 ctl_set_busy(&io->scsiio); 2503 io->scsiio.be_move_done(io); 2504 cfiscsi_session_terminate(cs); 2505 return; 2506 } 2507 sg_addr += len; 2508 sg_len -= len; 2509 2510 KASSERT(buffer_offset + response->ip_data_len <= expected_len, 2511 ("buffer_offset %zd + ip_data_len %zd > expected_len %zd", 2512 buffer_offset, response->ip_data_len, expected_len)); 2513 if (buffer_offset + response->ip_data_len == expected_len) { 2514 /* 2515 * Already have the amount of data the initiator wanted. 2516 */ 2517 break; 2518 } 2519 2520 if (sg_len == 0) { 2521 /* 2522 * End of scatter-gather segment; 2523 * proceed to the next one... 2524 */ 2525 if (i == ctl_sg_count - 1) { 2526 /* 2527 * ... unless this was the last one. 2528 */ 2529 break; 2530 } 2531 i++; 2532 } 2533 2534 if (response->ip_data_len == cs->cs_max_data_segment_length) { 2535 /* 2536 * Can't stuff more data into the current PDU; 2537 * queue it. Note that's not enough to check 2538 * for kern_data_resid == 0 instead; there 2539 * may be several Data-In PDUs for the final 2540 * call to cfiscsi_datamove(), and we want 2541 * to set the F flag only on the last of them. 2542 */ 2543 buffer_offset += response->ip_data_len; 2544 if (buffer_offset == io->scsiio.kern_total_len || 2545 buffer_offset == expected_len) { 2546 buffer_offset -= response->ip_data_len; 2547 break; 2548 } 2549 cfiscsi_pdu_queue(response); 2550 response = NULL; 2551 bhsdi = NULL; 2552 } 2553 } 2554 if (response != NULL) { 2555 buffer_offset += response->ip_data_len; 2556 if (buffer_offset == io->scsiio.kern_total_len || 2557 buffer_offset == expected_len) { 2558 bhsdi->bhsdi_flags |= BHSDI_FLAGS_F; 2559 if (io->io_hdr.status == CTL_SUCCESS) { 2560 bhsdi->bhsdi_flags |= BHSDI_FLAGS_S; 2561 if (PDU_TOTAL_TRANSFER_LEN(request) < 2562 ntohl(bhssc->bhssc_expected_data_transfer_length)) { 2563 bhsdi->bhsdi_flags |= BHSSR_FLAGS_RESIDUAL_UNDERFLOW; 2564 bhsdi->bhsdi_residual_count = 2565 htonl(ntohl(bhssc->bhssc_expected_data_transfer_length) - 2566 PDU_TOTAL_TRANSFER_LEN(request)); 2567 } else if (PDU_TOTAL_TRANSFER_LEN(request) > 2568 ntohl(bhssc->bhssc_expected_data_transfer_length)) { 2569 bhsdi->bhsdi_flags |= BHSSR_FLAGS_RESIDUAL_OVERFLOW; 2570 bhsdi->bhsdi_residual_count = 2571 htonl(PDU_TOTAL_TRANSFER_LEN(request) - 2572 ntohl(bhssc->bhssc_expected_data_transfer_length)); 2573 } 2574 bhsdi->bhsdi_status = io->scsiio.scsi_status; 2575 io->io_hdr.flags |= CTL_FLAG_STATUS_SENT; 2576 } 2577 } 2578 KASSERT(response->ip_data_len > 0, ("sending empty Data-In")); 2579 cfiscsi_pdu_queue(response); 2580 } 2581 2582 io->scsiio.be_move_done(io); 2583 } 2584 2585 static void 2586 cfiscsi_datamove_out(union ctl_io *io) 2587 { 2588 struct cfiscsi_session *cs; 2589 struct icl_pdu *request, *response; 2590 const struct iscsi_bhs_scsi_command *bhssc; 2591 struct iscsi_bhs_r2t *bhsr2t; 2592 struct cfiscsi_data_wait *cdw; 2593 struct ctl_sg_entry ctl_sg_entry, *ctl_sglist; 2594 uint32_t expected_len, r2t_off, r2t_len; 2595 uint32_t target_transfer_tag; 2596 bool done; 2597 2598 request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 2599 cs = PDU_SESSION(request); 2600 2601 bhssc = (const struct iscsi_bhs_scsi_command *)request->ip_bhs; 2602 KASSERT((bhssc->bhssc_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) == 2603 ISCSI_BHS_OPCODE_SCSI_COMMAND, 2604 ("bhssc->bhssc_opcode != ISCSI_BHS_OPCODE_SCSI_COMMAND")); 2605 2606 /* 2607 * We need to record it so that we can properly report 2608 * underflow/underflow. 2609 */ 2610 PDU_TOTAL_TRANSFER_LEN(request) = io->scsiio.kern_total_len; 2611 2612 /* 2613 * Report write underflow as error since CTL and backends don't 2614 * really support it, and SCSI does not tell how to do it right. 2615 */ 2616 expected_len = ntohl(bhssc->bhssc_expected_data_transfer_length); 2617 if (io->scsiio.kern_rel_offset + io->scsiio.kern_data_len > 2618 expected_len) { 2619 io->scsiio.io_hdr.port_status = 43; 2620 io->scsiio.be_move_done(io); 2621 return; 2622 } 2623 2624 target_transfer_tag = 2625 atomic_fetchadd_32(&cs->cs_target_transfer_tag, 1); 2626 cdw = cfiscsi_data_wait_new(cs, io, bhssc->bhssc_initiator_task_tag, 2627 &target_transfer_tag); 2628 if (cdw == NULL) { 2629 CFISCSI_SESSION_WARN(cs, "failed to " 2630 "allocate memory; dropping connection"); 2631 ctl_set_busy(&io->scsiio); 2632 io->scsiio.be_move_done(io); 2633 cfiscsi_session_terminate(cs); 2634 return; 2635 } 2636 #if 0 2637 CFISCSI_SESSION_DEBUG(cs, "expecting Data-Out with initiator " 2638 "task tag 0x%x, target transfer tag 0x%x", 2639 bhssc->bhssc_initiator_task_tag, target_transfer_tag); 2640 #endif 2641 2642 cdw->cdw_ctl_io = io; 2643 cdw->cdw_target_transfer_tag = target_transfer_tag; 2644 cdw->cdw_initiator_task_tag = bhssc->bhssc_initiator_task_tag; 2645 cdw->cdw_r2t_end = io->scsiio.kern_data_len; 2646 cdw->cdw_datasn = 0; 2647 2648 /* Set initial data pointer for the CDW respecting ext_data_filled. */ 2649 if (io->scsiio.kern_sg_entries > 0) { 2650 ctl_sglist = (struct ctl_sg_entry *)io->scsiio.kern_data_ptr; 2651 } else { 2652 ctl_sglist = &ctl_sg_entry; 2653 ctl_sglist->addr = io->scsiio.kern_data_ptr; 2654 ctl_sglist->len = io->scsiio.kern_data_len; 2655 } 2656 cdw->cdw_sg_index = 0; 2657 cdw->cdw_sg_addr = ctl_sglist[cdw->cdw_sg_index].addr; 2658 cdw->cdw_sg_len = ctl_sglist[cdw->cdw_sg_index].len; 2659 r2t_off = io->scsiio.ext_data_filled; 2660 while (r2t_off > 0) { 2661 if (r2t_off >= cdw->cdw_sg_len) { 2662 r2t_off -= cdw->cdw_sg_len; 2663 cdw->cdw_sg_index++; 2664 cdw->cdw_sg_addr = ctl_sglist[cdw->cdw_sg_index].addr; 2665 cdw->cdw_sg_len = ctl_sglist[cdw->cdw_sg_index].len; 2666 continue; 2667 } 2668 cdw->cdw_sg_addr += r2t_off; 2669 cdw->cdw_sg_len -= r2t_off; 2670 r2t_off = 0; 2671 } 2672 2673 if (cs->cs_immediate_data && 2674 io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled < 2675 icl_pdu_data_segment_length(request)) { 2676 done = cfiscsi_handle_data_segment(request, cdw); 2677 if (done) { 2678 cfiscsi_data_wait_free(cs, cdw); 2679 io->scsiio.be_move_done(io); 2680 return; 2681 } 2682 } 2683 2684 r2t_off = io->scsiio.kern_rel_offset + io->scsiio.ext_data_filled; 2685 r2t_len = MIN(io->scsiio.kern_data_len - io->scsiio.ext_data_filled, 2686 cs->cs_max_burst_length); 2687 cdw->cdw_r2t_end = io->scsiio.ext_data_filled + r2t_len; 2688 2689 CFISCSI_SESSION_LOCK(cs); 2690 TAILQ_INSERT_TAIL(&cs->cs_waiting_for_data_out, cdw, cdw_next); 2691 CFISCSI_SESSION_UNLOCK(cs); 2692 2693 /* 2694 * XXX: We should limit the number of outstanding R2T PDUs 2695 * per task to MaxOutstandingR2T. 2696 */ 2697 response = cfiscsi_pdu_new_response(request, M_NOWAIT); 2698 if (response == NULL) { 2699 CFISCSI_SESSION_WARN(cs, "failed to " 2700 "allocate memory; dropping connection"); 2701 ctl_set_busy(&io->scsiio); 2702 io->scsiio.be_move_done(io); 2703 cfiscsi_session_terminate(cs); 2704 return; 2705 } 2706 bhsr2t = (struct iscsi_bhs_r2t *)response->ip_bhs; 2707 bhsr2t->bhsr2t_opcode = ISCSI_BHS_OPCODE_R2T; 2708 bhsr2t->bhsr2t_flags = 0x80; 2709 bhsr2t->bhsr2t_lun = bhssc->bhssc_lun; 2710 bhsr2t->bhsr2t_initiator_task_tag = bhssc->bhssc_initiator_task_tag; 2711 bhsr2t->bhsr2t_target_transfer_tag = target_transfer_tag; 2712 /* 2713 * XXX: Here we assume that cfiscsi_datamove() won't ever 2714 * be running concurrently on several CPUs for a given 2715 * command. 2716 */ 2717 bhsr2t->bhsr2t_r2tsn = htonl(PDU_R2TSN(request)); 2718 PDU_R2TSN(request)++; 2719 /* 2720 * This is the offset within the current SCSI command; 2721 * i.e. for the first call of datamove(), it will be 0, 2722 * and for subsequent ones it will be the sum of lengths 2723 * of previous ones. 2724 * 2725 * The ext_data_filled is to account for unsolicited 2726 * (immediate) data that might have already arrived. 2727 */ 2728 bhsr2t->bhsr2t_buffer_offset = htonl(r2t_off); 2729 /* 2730 * This is the total length (sum of S/G lengths) this call 2731 * to cfiscsi_datamove() is supposed to handle, limited by 2732 * MaxBurstLength. 2733 */ 2734 bhsr2t->bhsr2t_desired_data_transfer_length = htonl(r2t_len); 2735 cfiscsi_pdu_queue(response); 2736 } 2737 2738 static void 2739 cfiscsi_datamove(union ctl_io *io) 2740 { 2741 2742 if ((io->io_hdr.flags & CTL_FLAG_DATA_MASK) == CTL_FLAG_DATA_IN) 2743 cfiscsi_datamove_in(io); 2744 else { 2745 /* We hadn't received anything during this datamove yet. */ 2746 io->scsiio.ext_data_filled = 0; 2747 cfiscsi_datamove_out(io); 2748 } 2749 } 2750 2751 static void 2752 cfiscsi_scsi_command_done(union ctl_io *io) 2753 { 2754 struct icl_pdu *request, *response; 2755 struct iscsi_bhs_scsi_command *bhssc; 2756 struct iscsi_bhs_scsi_response *bhssr; 2757 #ifdef DIAGNOSTIC 2758 struct cfiscsi_data_wait *cdw; 2759 #endif 2760 struct cfiscsi_session *cs; 2761 uint16_t sense_length; 2762 2763 request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 2764 cs = PDU_SESSION(request); 2765 bhssc = (struct iscsi_bhs_scsi_command *)request->ip_bhs; 2766 KASSERT((bhssc->bhssc_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) == 2767 ISCSI_BHS_OPCODE_SCSI_COMMAND, 2768 ("replying to wrong opcode 0x%x", bhssc->bhssc_opcode)); 2769 2770 //CFISCSI_SESSION_DEBUG(cs, "initiator task tag 0x%x", 2771 // bhssc->bhssc_initiator_task_tag); 2772 2773 #ifdef DIAGNOSTIC 2774 CFISCSI_SESSION_LOCK(cs); 2775 TAILQ_FOREACH(cdw, &cs->cs_waiting_for_data_out, cdw_next) 2776 KASSERT(bhssc->bhssc_initiator_task_tag != 2777 cdw->cdw_initiator_task_tag, ("dangling cdw")); 2778 CFISCSI_SESSION_UNLOCK(cs); 2779 #endif 2780 2781 /* 2782 * Do not return status for aborted commands. 2783 * There are exceptions, but none supported by CTL yet. 2784 */ 2785 if (((io->io_hdr.flags & CTL_FLAG_ABORT) && 2786 (io->io_hdr.flags & CTL_FLAG_ABORT_STATUS) == 0) || 2787 (io->io_hdr.flags & CTL_FLAG_STATUS_SENT)) { 2788 ctl_free_io(io); 2789 icl_pdu_free(request); 2790 return; 2791 } 2792 2793 response = cfiscsi_pdu_new_response(request, M_WAITOK); 2794 bhssr = (struct iscsi_bhs_scsi_response *)response->ip_bhs; 2795 bhssr->bhssr_opcode = ISCSI_BHS_OPCODE_SCSI_RESPONSE; 2796 bhssr->bhssr_flags = 0x80; 2797 /* 2798 * XXX: We don't deal with bidirectional under/overflows; 2799 * does anything actually support those? 2800 */ 2801 if (PDU_TOTAL_TRANSFER_LEN(request) < 2802 ntohl(bhssc->bhssc_expected_data_transfer_length)) { 2803 bhssr->bhssr_flags |= BHSSR_FLAGS_RESIDUAL_UNDERFLOW; 2804 bhssr->bhssr_residual_count = 2805 htonl(ntohl(bhssc->bhssc_expected_data_transfer_length) - 2806 PDU_TOTAL_TRANSFER_LEN(request)); 2807 //CFISCSI_SESSION_DEBUG(cs, "underflow; residual count %d", 2808 // ntohl(bhssr->bhssr_residual_count)); 2809 } else if (PDU_TOTAL_TRANSFER_LEN(request) > 2810 ntohl(bhssc->bhssc_expected_data_transfer_length)) { 2811 bhssr->bhssr_flags |= BHSSR_FLAGS_RESIDUAL_OVERFLOW; 2812 bhssr->bhssr_residual_count = 2813 htonl(PDU_TOTAL_TRANSFER_LEN(request) - 2814 ntohl(bhssc->bhssc_expected_data_transfer_length)); 2815 //CFISCSI_SESSION_DEBUG(cs, "overflow; residual count %d", 2816 // ntohl(bhssr->bhssr_residual_count)); 2817 } 2818 bhssr->bhssr_response = BHSSR_RESPONSE_COMMAND_COMPLETED; 2819 bhssr->bhssr_status = io->scsiio.scsi_status; 2820 bhssr->bhssr_initiator_task_tag = bhssc->bhssc_initiator_task_tag; 2821 bhssr->bhssr_expdatasn = htonl(PDU_EXPDATASN(request)); 2822 2823 if (io->scsiio.sense_len > 0) { 2824 #if 0 2825 CFISCSI_SESSION_DEBUG(cs, "returning %d bytes of sense data", 2826 io->scsiio.sense_len); 2827 #endif 2828 sense_length = htons(io->scsiio.sense_len); 2829 icl_pdu_append_data(response, 2830 &sense_length, sizeof(sense_length), M_WAITOK); 2831 icl_pdu_append_data(response, 2832 &io->scsiio.sense_data, io->scsiio.sense_len, M_WAITOK); 2833 } 2834 2835 ctl_free_io(io); 2836 icl_pdu_free(request); 2837 cfiscsi_pdu_queue(response); 2838 } 2839 2840 static void 2841 cfiscsi_task_management_done(union ctl_io *io) 2842 { 2843 struct icl_pdu *request, *response; 2844 struct iscsi_bhs_task_management_request *bhstmr; 2845 struct iscsi_bhs_task_management_response *bhstmr2; 2846 struct cfiscsi_data_wait *cdw, *tmpcdw; 2847 struct cfiscsi_session *cs; 2848 2849 request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 2850 cs = PDU_SESSION(request); 2851 bhstmr = (struct iscsi_bhs_task_management_request *)request->ip_bhs; 2852 KASSERT((bhstmr->bhstmr_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) == 2853 ISCSI_BHS_OPCODE_TASK_REQUEST, 2854 ("replying to wrong opcode 0x%x", bhstmr->bhstmr_opcode)); 2855 2856 #if 0 2857 CFISCSI_SESSION_DEBUG(cs, "initiator task tag 0x%x; referenced task tag 0x%x", 2858 bhstmr->bhstmr_initiator_task_tag, 2859 bhstmr->bhstmr_referenced_task_tag); 2860 #endif 2861 2862 if ((bhstmr->bhstmr_function & ~0x80) == 2863 BHSTMR_FUNCTION_ABORT_TASK) { 2864 /* 2865 * Make sure we no longer wait for Data-Out for this command. 2866 */ 2867 CFISCSI_SESSION_LOCK(cs); 2868 TAILQ_FOREACH_SAFE(cdw, 2869 &cs->cs_waiting_for_data_out, cdw_next, tmpcdw) { 2870 if (bhstmr->bhstmr_referenced_task_tag != 2871 cdw->cdw_initiator_task_tag) 2872 continue; 2873 2874 #if 0 2875 CFISCSI_SESSION_DEBUG(cs, "removing csw for initiator task " 2876 "tag 0x%x", bhstmr->bhstmr_initiator_task_tag); 2877 #endif 2878 TAILQ_REMOVE(&cs->cs_waiting_for_data_out, 2879 cdw, cdw_next); 2880 cdw->cdw_ctl_io->scsiio.be_move_done(cdw->cdw_ctl_io); 2881 cfiscsi_data_wait_free(cs, cdw); 2882 } 2883 CFISCSI_SESSION_UNLOCK(cs); 2884 } 2885 2886 response = cfiscsi_pdu_new_response(request, M_WAITOK); 2887 bhstmr2 = (struct iscsi_bhs_task_management_response *) 2888 response->ip_bhs; 2889 bhstmr2->bhstmr_opcode = ISCSI_BHS_OPCODE_TASK_RESPONSE; 2890 bhstmr2->bhstmr_flags = 0x80; 2891 if (io->io_hdr.status == CTL_SUCCESS) { 2892 bhstmr2->bhstmr_response = BHSTMR_RESPONSE_FUNCTION_COMPLETE; 2893 } else { 2894 /* 2895 * XXX: How to figure out what exactly went wrong? iSCSI spec 2896 * expects us to provide detailed error, e.g. "Task does 2897 * not exist" or "LUN does not exist". 2898 */ 2899 CFISCSI_SESSION_DEBUG(cs, "BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED"); 2900 bhstmr2->bhstmr_response = 2901 BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED; 2902 } 2903 bhstmr2->bhstmr_initiator_task_tag = bhstmr->bhstmr_initiator_task_tag; 2904 2905 ctl_free_io(io); 2906 icl_pdu_free(request); 2907 cfiscsi_pdu_queue(response); 2908 } 2909 2910 static void 2911 cfiscsi_done(union ctl_io *io) 2912 { 2913 struct icl_pdu *request; 2914 struct cfiscsi_session *cs; 2915 2916 KASSERT(((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE), 2917 ("invalid CTL status %#x", io->io_hdr.status)); 2918 2919 if (io->io_hdr.io_type == CTL_IO_TASK && 2920 io->taskio.task_action == CTL_TASK_I_T_NEXUS_RESET) { 2921 /* 2922 * Implicit task termination has just completed; nothing to do. 2923 */ 2924 cs = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 2925 cs->cs_tasks_aborted = true; 2926 refcount_release(&cs->cs_outstanding_ctl_pdus); 2927 wakeup(__DEVOLATILE(void *, &cs->cs_outstanding_ctl_pdus)); 2928 ctl_free_io(io); 2929 return; 2930 } 2931 2932 request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 2933 cs = PDU_SESSION(request); 2934 refcount_release(&cs->cs_outstanding_ctl_pdus); 2935 2936 switch (request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) { 2937 case ISCSI_BHS_OPCODE_SCSI_COMMAND: 2938 cfiscsi_scsi_command_done(io); 2939 break; 2940 case ISCSI_BHS_OPCODE_TASK_REQUEST: 2941 cfiscsi_task_management_done(io); 2942 break; 2943 default: 2944 panic("cfiscsi_done called with wrong opcode 0x%x", 2945 request->ip_bhs->bhs_opcode); 2946 } 2947 } 2948