diff options
Diffstat (limited to 'sys/cam/ctl/ctl_frontend_iscsi.c')
-rw-r--r-- | sys/cam/ctl/ctl_frontend_iscsi.c | 209 |
1 files changed, 129 insertions, 80 deletions
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c index e19852a..778a6ba 100644 --- a/sys/cam/ctl/ctl_frontend_iscsi.c +++ b/sys/cam/ctl/ctl_frontend_iscsi.c @@ -61,7 +61,6 @@ __FBSDID("$FreeBSD$"); #include <cam/ctl/ctl_backend.h> #include <cam/ctl/ctl_error.h> #include <cam/ctl/ctl_frontend.h> -#include <cam/ctl/ctl_frontend_internal.h> #include <cam/ctl/ctl_debug.h> #include <cam/ctl/ctl_ha.h> #include <cam/ctl/ctl_ioctl.h> @@ -150,8 +149,6 @@ int cfiscsi_init(void); static void cfiscsi_online(void *arg); static void cfiscsi_offline(void *arg); static int cfiscsi_info(void *arg, struct sbuf *sb); -static int cfiscsi_lun_enable(void *arg, int lun_id); -static int cfiscsi_lun_disable(void *arg, int lun_id); static int cfiscsi_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td); static void cfiscsi_datamove(union ctl_io *io); @@ -174,7 +171,6 @@ static void cfiscsi_target_release(struct cfiscsi_target *ct); static void cfiscsi_session_delete(struct cfiscsi_session *cs); static struct cfiscsi_softc cfiscsi_softc; -extern struct ctl_softc *control_softc; static struct ctl_frontend cfiscsi_frontend = { @@ -462,6 +458,7 @@ cfiscsi_decode_lun(uint64_t encoded) break; } result = (lun[1] << 16) + (lun[2] << 8) + lun[3]; + break; default: CFISCSI_WARN("unsupported LUN format 0x%jx", (uintmax_t)encoded); @@ -564,9 +561,8 @@ cfiscsi_pdu_handle_scsi_command(struct icl_pdu *request) ctl_zero_io(io); io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = request; io->io_hdr.io_type = CTL_IO_SCSI; - io->io_hdr.nexus.initid.id = cs->cs_ctl_initid; + io->io_hdr.nexus.initid = cs->cs_ctl_initid; io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port; - io->io_hdr.nexus.targ_target.id = 0; io->io_hdr.nexus.targ_lun = cfiscsi_decode_lun(bhssc->bhssc_lun); io->scsiio.tag_num = bhssc->bhssc_initiator_task_tag; switch ((bhssc->bhssc_flags & BHSSC_FLAGS_ATTR)) { @@ -621,9 +617,8 @@ cfiscsi_pdu_handle_task_request(struct icl_pdu *request) ctl_zero_io(io); io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = request; io->io_hdr.io_type = CTL_IO_TASK; - io->io_hdr.nexus.initid.id = cs->cs_ctl_initid; + io->io_hdr.nexus.initid = cs->cs_ctl_initid; io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port; - io->io_hdr.nexus.targ_target.id = 0; io->io_hdr.nexus.targ_lun = cfiscsi_decode_lun(bhstmr->bhstmr_lun); io->taskio.tag_type = CTL_TAG_SIMPLE; /* XXX */ @@ -641,6 +636,12 @@ cfiscsi_pdu_handle_task_request(struct icl_pdu *request) #endif io->taskio.task_action = CTL_TASK_ABORT_TASK_SET; break; + case BHSTMR_FUNCTION_CLEAR_TASK_SET: +#if 0 + CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_CLEAR_TASK_SET"); +#endif + io->taskio.task_action = CTL_TASK_CLEAR_TASK_SET; + break; case BHSTMR_FUNCTION_LOGICAL_UNIT_RESET: #if 0 CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_LOGICAL_UNIT_RESET"); @@ -653,6 +654,37 @@ cfiscsi_pdu_handle_task_request(struct icl_pdu *request) #endif io->taskio.task_action = CTL_TASK_TARGET_RESET; break; + case BHSTMR_FUNCTION_TARGET_COLD_RESET: +#if 0 + CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_TARGET_COLD_RESET"); +#endif + io->taskio.task_action = CTL_TASK_TARGET_RESET; + break; + case BHSTMR_FUNCTION_QUERY_TASK: +#if 0 + CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_QUERY_TASK"); +#endif + io->taskio.task_action = CTL_TASK_QUERY_TASK; + io->taskio.tag_num = bhstmr->bhstmr_referenced_task_tag; + break; + case BHSTMR_FUNCTION_QUERY_TASK_SET: +#if 0 + CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_QUERY_TASK_SET"); +#endif + io->taskio.task_action = CTL_TASK_QUERY_TASK_SET; + break; + case BHSTMR_FUNCTION_I_T_NEXUS_RESET: +#if 0 + CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_I_T_NEXUS_RESET"); +#endif + io->taskio.task_action = CTL_TASK_I_T_NEXUS_RESET; + break; + case BHSTMR_FUNCTION_QUERY_ASYNC_EVENT: +#if 0 + CFISCSI_SESSION_DEBUG(cs, "BHSTMR_FUNCTION_QUERY_ASYNC_EVENT"); +#endif + io->taskio.task_action = CTL_TASK_QUERY_ASYNC_EVENT; + break; default: CFISCSI_SESSION_DEBUG(cs, "unsupported function 0x%x", bhstmr->bhstmr_function & ~0x80); @@ -931,6 +963,7 @@ cfiscsi_pdu_handle_data_out(struct icl_pdu *request) done = (io->scsiio.ext_data_filled != cdw->cdw_r2t_end || io->scsiio.ext_data_filled == io->scsiio.kern_data_len); uma_zfree(cfiscsi_data_wait_zone, cdw); + io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG; if (done) io->scsiio.be_move_done(io); else @@ -1081,9 +1114,8 @@ cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs) ctl_zero_io(io); io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = cs; io->io_hdr.io_type = CTL_IO_TASK; - io->io_hdr.nexus.initid.id = cs->cs_ctl_initid; + io->io_hdr.nexus.initid = cs->cs_ctl_initid; io->io_hdr.nexus.targ_port = cs->cs_target->ct_port.targ_port; - io->io_hdr.nexus.targ_target.id = 0; io->io_hdr.nexus.targ_lun = 0; io->taskio.tag_type = CTL_TAG_SIMPLE; /* XXX */ io->taskio.task_action = CTL_TASK_I_T_NEXUS_RESET; @@ -1105,6 +1137,7 @@ cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs) * assuming that the data transfer actually succeeded * and writing uninitialized data to disk. */ + cdw->cdw_ctl_io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG; cdw->cdw_ctl_io->scsiio.io_hdr.port_status = 42; cdw->cdw_ctl_io->scsiio.be_move_done(cdw->cdw_ctl_io); uma_zfree(cfiscsi_data_wait_zone, cdw); @@ -1299,10 +1332,8 @@ int cfiscsi_init(void) { struct cfiscsi_softc *softc; - int retval; softc = &cfiscsi_softc; - retval = 0; bzero(softc, sizeof(*softc)); mtx_init(&softc->lock, "cfiscsi", NULL, MTX_DEF); @@ -1532,6 +1563,16 @@ restart: if (cs2 != cs && cs2->cs_tasks_aborted == false && cs->cs_target == cs2->cs_target && strcmp(cs->cs_initiator_id, cs2->cs_initiator_id) == 0) { + if (strcmp(cs->cs_initiator_addr, + cs2->cs_initiator_addr) != 0) { + CFISCSI_SESSION_WARN(cs2, + "session reinstatement from " + "different address %s", + cs->cs_initiator_addr); + } else { + CFISCSI_SESSION_DEBUG(cs2, + "session reinstatement"); + } cfiscsi_session_terminate(cs2); mtx_unlock(&softc->lock); pause("cfiscsi_reinstate", 1); @@ -1652,41 +1693,40 @@ cfiscsi_ioctl_list(struct ctl_iscsi *ci) } static void -cfiscsi_ioctl_terminate(struct ctl_iscsi *ci) +cfiscsi_ioctl_logout(struct ctl_iscsi *ci) { struct icl_pdu *response; struct iscsi_bhs_asynchronous_message *bhsam; - struct ctl_iscsi_terminate_params *citp; + struct ctl_iscsi_logout_params *cilp; struct cfiscsi_session *cs; struct cfiscsi_softc *softc; int found = 0; - citp = (struct ctl_iscsi_terminate_params *)&(ci->data); + cilp = (struct ctl_iscsi_logout_params *)&(ci->data); softc = &cfiscsi_softc; mtx_lock(&softc->lock); TAILQ_FOREACH(cs, &softc->sessions, cs_next) { - if (citp->all == 0 && cs->cs_id != citp->connection_id && - strcmp(cs->cs_initiator_name, citp->initiator_name) != 0 && - strcmp(cs->cs_initiator_addr, citp->initiator_addr) != 0) + if (cilp->all == 0 && cs->cs_id != cilp->connection_id && + strcmp(cs->cs_initiator_name, cilp->initiator_name) != 0 && + strcmp(cs->cs_initiator_addr, cilp->initiator_addr) != 0) continue; response = icl_pdu_new(cs->cs_conn, M_NOWAIT); if (response == NULL) { - /* - * Oh well. Just terminate the connection. - */ - } else { - bhsam = (struct iscsi_bhs_asynchronous_message *) - response->ip_bhs; - bhsam->bhsam_opcode = ISCSI_BHS_OPCODE_ASYNC_MESSAGE; - bhsam->bhsam_flags = 0x80; - bhsam->bhsam_0xffffffff = 0xffffffff; - bhsam->bhsam_async_event = - BHSAM_EVENT_TARGET_TERMINATES_SESSION; - cfiscsi_pdu_queue(response); + ci->status = CTL_ISCSI_ERROR; + snprintf(ci->error_str, sizeof(ci->error_str), + "Unable to allocate memory"); + mtx_unlock(&softc->lock); + return; } - cfiscsi_session_terminate(cs); + bhsam = + (struct iscsi_bhs_asynchronous_message *)response->ip_bhs; + bhsam->bhsam_opcode = ISCSI_BHS_OPCODE_ASYNC_MESSAGE; + bhsam->bhsam_flags = 0x80; + bhsam->bhsam_async_event = BHSAM_EVENT_TARGET_REQUESTS_LOGOUT; + bhsam->bhsam_parameter3 = htons(10); + cfiscsi_pdu_queue(response); found++; } mtx_unlock(&softc->lock); @@ -1702,40 +1742,41 @@ cfiscsi_ioctl_terminate(struct ctl_iscsi *ci) } static void -cfiscsi_ioctl_logout(struct ctl_iscsi *ci) +cfiscsi_ioctl_terminate(struct ctl_iscsi *ci) { struct icl_pdu *response; struct iscsi_bhs_asynchronous_message *bhsam; - struct ctl_iscsi_logout_params *cilp; + struct ctl_iscsi_terminate_params *citp; struct cfiscsi_session *cs; struct cfiscsi_softc *softc; int found = 0; - cilp = (struct ctl_iscsi_logout_params *)&(ci->data); + citp = (struct ctl_iscsi_terminate_params *)&(ci->data); softc = &cfiscsi_softc; mtx_lock(&softc->lock); TAILQ_FOREACH(cs, &softc->sessions, cs_next) { - if (cilp->all == 0 && cs->cs_id != cilp->connection_id && - strcmp(cs->cs_initiator_name, cilp->initiator_name) != 0 && - strcmp(cs->cs_initiator_addr, cilp->initiator_addr) != 0) + if (citp->all == 0 && cs->cs_id != citp->connection_id && + strcmp(cs->cs_initiator_name, citp->initiator_name) != 0 && + strcmp(cs->cs_initiator_addr, citp->initiator_addr) != 0) continue; response = icl_pdu_new(cs->cs_conn, M_NOWAIT); if (response == NULL) { - ci->status = CTL_ISCSI_ERROR; - snprintf(ci->error_str, sizeof(ci->error_str), - "Unable to allocate memory"); - mtx_unlock(&softc->lock); - return; + /* + * Oh well. Just terminate the connection. + */ + } else { + bhsam = (struct iscsi_bhs_asynchronous_message *) + response->ip_bhs; + bhsam->bhsam_opcode = ISCSI_BHS_OPCODE_ASYNC_MESSAGE; + bhsam->bhsam_flags = 0x80; + bhsam->bhsam_0xffffffff = 0xffffffff; + bhsam->bhsam_async_event = + BHSAM_EVENT_TARGET_TERMINATES_SESSION; + cfiscsi_pdu_queue(response); } - bhsam = - (struct iscsi_bhs_asynchronous_message *)response->ip_bhs; - bhsam->bhsam_opcode = ISCSI_BHS_OPCODE_ASYNC_MESSAGE; - bhsam->bhsam_flags = 0x80; - bhsam->bhsam_async_event = BHSAM_EVENT_TARGET_REQUESTS_LOGOUT; - bhsam->bhsam_parameter3 = htons(10); - cfiscsi_pdu_queue(response); + cfiscsi_session_terminate(cs); found++; } mtx_unlock(&softc->lock); @@ -2032,9 +2073,6 @@ cfiscsi_ioctl_port_create(struct ctl_req *req) port->port_offline = cfiscsi_offline; port->port_info = cfiscsi_info; port->onoff_arg = ct; - port->lun_enable = cfiscsi_lun_enable; - port->lun_disable = cfiscsi_lun_disable; - port->targ_lun_arg = ct; port->fe_datamove = cfiscsi_datamove; port->fe_done = cfiscsi_done; @@ -2042,6 +2080,7 @@ cfiscsi_ioctl_port_create(struct ctl_req *req) /* XXX These should probably be fetched from CTL. */ port->max_targets = 1; port->max_target_id = 15; + port->targ_port = -1; port->options = opts; STAILQ_INIT(&opts); @@ -2170,12 +2209,12 @@ cfiscsi_ioctl(struct cdev *dev, case CTL_ISCSI_LIST: cfiscsi_ioctl_list(ci); break; - case CTL_ISCSI_TERMINATE: - cfiscsi_ioctl_terminate(ci); - break; case CTL_ISCSI_LOGOUT: cfiscsi_ioctl_logout(ci); break; + case CTL_ISCSI_TERMINATE: + cfiscsi_ioctl_terminate(ci); + break; #ifdef ICL_KERNEL_PROXY case CTL_ISCSI_LISTEN: cfiscsi_ioctl_listen(ci); @@ -2298,20 +2337,6 @@ cfiscsi_target_find_or_create(struct cfiscsi_softc *softc, const char *name, return (newct); } -static int -cfiscsi_lun_enable(void *arg, int lun_id) -{ - - return (0); -} - -static int -cfiscsi_lun_disable(void *arg, int lun_id) -{ - - return (0); -} - static void cfiscsi_datamove_in(union ctl_io *io) { @@ -2650,6 +2675,7 @@ cfiscsi_datamove_out(union ctl_io *io) cfiscsi_session_terminate(cs); return; } + io->io_hdr.flags |= CTL_FLAG_DMA_INPROG; bhsr2t = (struct iscsi_bhs_r2t *)response->ip_bhs; bhsr2t->bhsr2t_opcode = ISCSI_BHS_OPCODE_R2T; bhsr2t->bhsr2t_flags = 0x80; @@ -2791,7 +2817,9 @@ cfiscsi_task_management_done(union ctl_io *io) struct iscsi_bhs_task_management_request *bhstmr; struct iscsi_bhs_task_management_response *bhstmr2; struct cfiscsi_data_wait *cdw, *tmpcdw; - struct cfiscsi_session *cs; + struct cfiscsi_session *cs, *tcs; + struct cfiscsi_softc *softc; + int cold_reset = 0; request = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; cs = PDU_SESSION(request); @@ -2824,34 +2852,55 @@ cfiscsi_task_management_done(union ctl_io *io) #endif TAILQ_REMOVE(&cs->cs_waiting_for_data_out, cdw, cdw_next); + io->io_hdr.flags &= ~CTL_FLAG_DMA_INPROG; + cdw->cdw_ctl_io->scsiio.io_hdr.port_status = 43; cdw->cdw_ctl_io->scsiio.be_move_done(cdw->cdw_ctl_io); uma_zfree(cfiscsi_data_wait_zone, cdw); } CFISCSI_SESSION_UNLOCK(cs); } + if ((bhstmr->bhstmr_function & ~0x80) == + BHSTMR_FUNCTION_TARGET_COLD_RESET && + io->io_hdr.status == CTL_SUCCESS) + cold_reset = 1; response = cfiscsi_pdu_new_response(request, M_WAITOK); bhstmr2 = (struct iscsi_bhs_task_management_response *) response->ip_bhs; bhstmr2->bhstmr_opcode = ISCSI_BHS_OPCODE_TASK_RESPONSE; bhstmr2->bhstmr_flags = 0x80; - if (io->io_hdr.status == CTL_SUCCESS) { + switch (io->taskio.task_status) { + case CTL_TASK_FUNCTION_COMPLETE: bhstmr2->bhstmr_response = BHSTMR_RESPONSE_FUNCTION_COMPLETE; - } else { - /* - * XXX: How to figure out what exactly went wrong? iSCSI spec - * expects us to provide detailed error, e.g. "Task does - * not exist" or "LUN does not exist". - */ - CFISCSI_SESSION_DEBUG(cs, "BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED"); - bhstmr2->bhstmr_response = - BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED; + break; + case CTL_TASK_FUNCTION_SUCCEEDED: + bhstmr2->bhstmr_response = BHSTMR_RESPONSE_FUNCTION_SUCCEEDED; + break; + case CTL_TASK_LUN_DOES_NOT_EXIST: + bhstmr2->bhstmr_response = BHSTMR_RESPONSE_LUN_DOES_NOT_EXIST; + break; + case CTL_TASK_FUNCTION_NOT_SUPPORTED: + default: + bhstmr2->bhstmr_response = BHSTMR_RESPONSE_FUNCTION_NOT_SUPPORTED; + break; } + memcpy(bhstmr2->bhstmr_additional_reponse_information, + io->taskio.task_resp, sizeof(io->taskio.task_resp)); bhstmr2->bhstmr_initiator_task_tag = bhstmr->bhstmr_initiator_task_tag; ctl_free_io(io); icl_pdu_free(request); cfiscsi_pdu_queue(response); + + if (cold_reset) { + softc = cs->cs_target->ct_softc; + mtx_lock(&softc->lock); + TAILQ_FOREACH(tcs, &softc->sessions, cs_next) { + if (tcs->cs_target == cs->cs_target) + cfiscsi_session_terminate(tcs); + } + mtx_unlock(&softc->lock); + } } static void |