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