summaryrefslogtreecommitdiffstats
path: root/sys/cam/ctl/ctl_frontend_iscsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam/ctl/ctl_frontend_iscsi.c')
-rw-r--r--sys/cam/ctl/ctl_frontend_iscsi.c209
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
OpenPOWER on IntegriCloud