Changeset View
Changeset View
Standalone View
Standalone View
sys/cam/ctl/ctl_frontend_iscsi.c
Show First 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | |||||
#ifdef ICL_KERNEL_PROXY | #ifdef ICL_KERNEL_PROXY | ||||
#include <sys/socketvar.h> | #include <sys/socketvar.h> | ||||
#endif | #endif | ||||
#ifdef ICL_KERNEL_PROXY | #ifdef ICL_KERNEL_PROXY | ||||
FEATURE(cfiscsi_kernel_proxy, "iSCSI target built with ICL_KERNEL_PROXY"); | FEATURE(cfiscsi_kernel_proxy, "iSCSI target built with ICL_KERNEL_PROXY"); | ||||
#endif | #endif | ||||
/* Used for internal nexus reset task. */ | |||||
#define ISCSI_BHS_OPCODE_INTERNAL 0x3e | |||||
static MALLOC_DEFINE(M_CFISCSI, "cfiscsi", "Memory used for CTL iSCSI frontend"); | static MALLOC_DEFINE(M_CFISCSI, "cfiscsi", "Memory used for CTL iSCSI frontend"); | ||||
static uma_zone_t cfiscsi_data_wait_zone; | static uma_zone_t cfiscsi_data_wait_zone; | ||||
SYSCTL_NODE(_kern_cam_ctl, OID_AUTO, iscsi, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | SYSCTL_NODE(_kern_cam_ctl, OID_AUTO, iscsi, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, | ||||
"CAM Target Layer iSCSI Frontend"); | "CAM Target Layer iSCSI Frontend"); | ||||
static int debug = 1; | static int debug = 1; | ||||
SYSCTL_INT(_kern_cam_ctl_iscsi, OID_AUTO, debug, CTLFLAG_RWTUN, | SYSCTL_INT(_kern_cam_ctl_iscsi, OID_AUTO, debug, CTLFLAG_RWTUN, | ||||
&debug, 1, "Enable debug messages"); | &debug, 1, "Enable debug messages"); | ||||
▲ Show 20 Lines • Show All 1,031 Lines • ▼ Show 20 Lines | cfiscsi_data_wait_abort(struct cfiscsi_session *cs, | ||||
cfiscsi_data_wait_free(cs, cdw); | cfiscsi_data_wait_free(cs, cdw); | ||||
ctl_datamove_done(cdw_io, false); | ctl_datamove_done(cdw_io, false); | ||||
} | } | ||||
static void | static void | ||||
cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs) | cfiscsi_session_terminate_tasks(struct cfiscsi_session *cs) | ||||
{ | { | ||||
struct cfiscsi_data_wait *cdw; | struct cfiscsi_data_wait *cdw; | ||||
struct icl_pdu *ip; | |||||
union ctl_io *io; | union ctl_io *io; | ||||
int error, last, wait; | int error, last, wait; | ||||
if (cs->cs_target == NULL) | if (cs->cs_target == NULL) | ||||
return; /* No target yet, so nothing to do. */ | return; /* No target yet, so nothing to do. */ | ||||
ip = icl_pdu_new(cs->cs_conn, M_WAITOK); | |||||
ip->ip_bhs->bhs_opcode = ISCSI_BHS_OPCODE_INTERNAL; | |||||
io = ctl_alloc_io(cs->cs_target->ct_port.ctl_pool_ref); | io = ctl_alloc_io(cs->cs_target->ct_port.ctl_pool_ref); | ||||
ctl_zero_io(io); | ctl_zero_io(io); | ||||
PRIV_REQUEST(io) = cs; | PRIV_REQUEST(io) = ip; | ||||
io->io_hdr.io_type = CTL_IO_TASK; | io->io_hdr.io_type = CTL_IO_TASK; | ||||
io->io_hdr.nexus.initid = 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_port = cs->cs_target->ct_port.targ_port; | ||||
io->io_hdr.nexus.targ_lun = 0; | io->io_hdr.nexus.targ_lun = 0; | ||||
io->taskio.tag_type = CTL_TAG_SIMPLE; /* XXX */ | io->taskio.tag_type = CTL_TAG_SIMPLE; /* XXX */ | ||||
io->taskio.task_action = CTL_TASK_I_T_NEXUS_RESET; | io->taskio.task_action = CTL_TASK_I_T_NEXUS_RESET; | ||||
wait = cs->cs_outstanding_ctl_pdus; | wait = cs->cs_outstanding_ctl_pdus; | ||||
refcount_acquire(&cs->cs_outstanding_ctl_pdus); | refcount_acquire(&cs->cs_outstanding_ctl_pdus); | ||||
error = ctl_run(io); | error = ctl_run(io); | ||||
if (error != CTL_RETVAL_COMPLETE) { | if (error != CTL_RETVAL_COMPLETE) { | ||||
CFISCSI_SESSION_WARN(cs, "ctl_run() failed; error %d", error); | CFISCSI_SESSION_WARN(cs, "ctl_run() failed; error %d", error); | ||||
refcount_release(&cs->cs_outstanding_ctl_pdus); | refcount_release(&cs->cs_outstanding_ctl_pdus); | ||||
ctl_free_io(io); | ctl_free_io(io); | ||||
icl_pdu_free(ip); | |||||
} | } | ||||
CFISCSI_SESSION_LOCK(cs); | CFISCSI_SESSION_LOCK(cs); | ||||
cs->cs_terminating_tasks = true; | cs->cs_terminating_tasks = true; | ||||
while ((cdw = TAILQ_FIRST(&cs->cs_waiting_for_data_out)) != NULL) { | while ((cdw = TAILQ_FIRST(&cs->cs_waiting_for_data_out)) != NULL) { | ||||
TAILQ_REMOVE(&cs->cs_waiting_for_data_out, cdw, cdw_next); | TAILQ_REMOVE(&cs->cs_waiting_for_data_out, cdw, cdw_next); | ||||
CFISCSI_SESSION_UNLOCK(cs); | CFISCSI_SESSION_UNLOCK(cs); | ||||
cfiscsi_data_wait_abort(cs, cdw, 42); | cfiscsi_data_wait_abort(cs, cdw, 42); | ||||
▲ Show 20 Lines • Show All 1,873 Lines • ▼ Show 20 Lines | |||||
cfiscsi_done(union ctl_io *io) | cfiscsi_done(union ctl_io *io) | ||||
{ | { | ||||
struct icl_pdu *request; | struct icl_pdu *request; | ||||
struct cfiscsi_session *cs; | struct cfiscsi_session *cs; | ||||
KASSERT(((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE), | KASSERT(((io->io_hdr.status & CTL_STATUS_MASK) != CTL_STATUS_NONE), | ||||
("invalid CTL status %#x", io->io_hdr.status)); | ("invalid CTL status %#x", io->io_hdr.status)); | ||||
if (io->io_hdr.io_type == CTL_IO_TASK && | |||||
io->taskio.task_action == CTL_TASK_I_T_NEXUS_RESET) { | |||||
/* | |||||
* Implicit task termination has just completed; nothing to do. | |||||
*/ | |||||
cs = PRIV_REQUEST(io); | |||||
cs->cs_tasks_aborted = true; | |||||
refcount_release(&cs->cs_outstanding_ctl_pdus); | |||||
wakeup(__DEVOLATILE(void *, &cs->cs_outstanding_ctl_pdus)); | |||||
ctl_free_io(io); | |||||
return; | |||||
} | |||||
request = PRIV_REQUEST(io); | request = PRIV_REQUEST(io); | ||||
cs = PDU_SESSION(request); | cs = PDU_SESSION(request); | ||||
switch (request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) { | switch (request->ip_bhs->bhs_opcode & ~ISCSI_BHS_OPCODE_IMMEDIATE) { | ||||
case ISCSI_BHS_OPCODE_SCSI_COMMAND: | case ISCSI_BHS_OPCODE_SCSI_COMMAND: | ||||
cfiscsi_scsi_command_done(io); | cfiscsi_scsi_command_done(io); | ||||
break; | break; | ||||
case ISCSI_BHS_OPCODE_TASK_REQUEST: | case ISCSI_BHS_OPCODE_TASK_REQUEST: | ||||
cfiscsi_task_management_done(io); | cfiscsi_task_management_done(io); | ||||
break; | break; | ||||
case ISCSI_BHS_OPCODE_INTERNAL: | |||||
/* | |||||
* Implicit task termination has just completed; nothing to do. | |||||
*/ | |||||
cs->cs_tasks_aborted = true; | |||||
refcount_release(&cs->cs_outstanding_ctl_pdus); | |||||
wakeup(__DEVOLATILE(void *, &cs->cs_outstanding_ctl_pdus)); | |||||
ctl_free_io(io); | |||||
icl_pdu_free(request); | |||||
return; | |||||
default: | default: | ||||
panic("cfiscsi_done called with wrong opcode 0x%x", | panic("cfiscsi_done called with wrong opcode 0x%x", | ||||
request->ip_bhs->bhs_opcode); | request->ip_bhs->bhs_opcode); | ||||
} | } | ||||
refcount_release(&cs->cs_outstanding_ctl_pdus); | refcount_release(&cs->cs_outstanding_ctl_pdus); | ||||
} | } |