Commit fbc514b4 authored by Mike Christie's avatar Mike Christie Committed by James Bottomley

[SCSI] iscsi_tcp: convert iscsi_tcp to support merged tasks

Convert iscsi_tcp to support merged tasks.
Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent 3e5c28ad
...@@ -498,11 +498,15 @@ iscsi_tcp_data_recv_prep(struct iscsi_tcp_conn *tcp_conn) ...@@ -498,11 +498,15 @@ iscsi_tcp_data_recv_prep(struct iscsi_tcp_conn *tcp_conn)
* must be called with session lock * must be called with session lock
*/ */
static void static void
iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) iscsi_tcp_cleanup_task(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
{ {
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
struct iscsi_r2t_info *r2t; struct iscsi_r2t_info *r2t;
/* nothing to do for mgmt ctasks */
if (!ctask->sc)
return;
/* flush ctask's r2t queues */ /* flush ctask's r2t queues */
while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) { while (__kfifo_get(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*))) {
__kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t, __kfifo_put(tcp_ctask->r2tpool.queue, (void*)&r2t,
...@@ -521,7 +525,7 @@ iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) ...@@ -521,7 +525,7 @@ iscsi_tcp_cleanup_ctask(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
/** /**
* iscsi_data_rsp - SCSI Data-In Response processing * iscsi_data_rsp - SCSI Data-In Response processing
* @conn: iscsi connection * @conn: iscsi connection
* @ctask: scsi command task * @ctask: scsi command ctask
**/ **/
static int static int
iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
...@@ -578,7 +582,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) ...@@ -578,7 +582,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
/** /**
* iscsi_solicit_data_init - initialize first Data-Out * iscsi_solicit_data_init - initialize first Data-Out
* @conn: iscsi connection * @conn: iscsi connection
* @ctask: scsi command task * @ctask: scsi command ctask
* @r2t: R2T info * @r2t: R2T info
* *
* Notes: * Notes:
...@@ -620,7 +624,7 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, ...@@ -620,7 +624,7 @@ iscsi_solicit_data_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
/** /**
* iscsi_r2t_rsp - iSCSI R2T Response processing * iscsi_r2t_rsp - iSCSI R2T Response processing
* @conn: iscsi connection * @conn: iscsi connection
* @ctask: scsi command task * @ctask: scsi command ctask
**/ **/
static int static int
iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
...@@ -646,7 +650,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) ...@@ -646,7 +650,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
return ISCSI_ERR_R2TSN; return ISCSI_ERR_R2TSN;
} }
/* fill-in new R2T associated with the task */ /* fill-in new R2T associated with the ctask */
iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr); iscsi_update_cmdsn(session, (struct iscsi_nopin*)rhdr);
if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) { if (!ctask->sc || session->state != ISCSI_STATE_LOGGED_IN) {
...@@ -769,6 +773,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) ...@@ -769,6 +773,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
ctask = iscsi_itt_to_ctask(conn, hdr->itt); ctask = iscsi_itt_to_ctask(conn, hdr->itt);
if (!ctask) if (!ctask)
return ISCSI_ERR_BAD_ITT; return ISCSI_ERR_BAD_ITT;
if (!ctask->sc)
return ISCSI_ERR_NO_SCSI_CMD;
spin_lock(&conn->session->lock); spin_lock(&conn->session->lock);
rc = iscsi_data_rsp(conn, ctask); rc = iscsi_data_rsp(conn, ctask);
...@@ -815,6 +821,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) ...@@ -815,6 +821,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
ctask = iscsi_itt_to_ctask(conn, hdr->itt); ctask = iscsi_itt_to_ctask(conn, hdr->itt);
if (!ctask) if (!ctask)
return ISCSI_ERR_BAD_ITT; return ISCSI_ERR_BAD_ITT;
if (!ctask->sc)
return ISCSI_ERR_NO_SCSI_CMD;
if (ahslen) if (ahslen)
rc = ISCSI_ERR_AHSLEN; rc = ISCSI_ERR_AHSLEN;
...@@ -1194,7 +1202,7 @@ iscsi_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, size_t hdrlen) ...@@ -1194,7 +1202,7 @@ iscsi_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr, size_t hdrlen)
/* If header digest is enabled, compute the CRC and /* If header digest is enabled, compute the CRC and
* place the digest into the same buffer. We make * place the digest into the same buffer. We make
* sure that both iscsi_tcp_ctask and mtask have * sure that both iscsi_tcp_cmd_task and mctask have
* sufficient room. * sufficient room.
*/ */
if (conn->hdrdgst_en) { if (conn->hdrdgst_en) {
...@@ -1269,7 +1277,7 @@ iscsi_tcp_send_linear_data_prepare(struct iscsi_conn *conn, void *data, ...@@ -1269,7 +1277,7 @@ iscsi_tcp_send_linear_data_prepare(struct iscsi_conn *conn, void *data,
/** /**
* iscsi_solicit_data_cont - initialize next Data-Out * iscsi_solicit_data_cont - initialize next Data-Out
* @conn: iscsi connection * @conn: iscsi connection
* @ctask: scsi command task * @ctask: scsi command ctask
* @r2t: R2T info * @r2t: R2T info
* @left: bytes left to transfer * @left: bytes left to transfer
* *
...@@ -1316,19 +1324,37 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, ...@@ -1316,19 +1324,37 @@ iscsi_solicit_data_cont(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask,
} }
/** /**
* iscsi_tcp_ctask - Initialize iSCSI SCSI_READ or SCSI_WRITE commands * iscsi_tcp_task - Initialize iSCSI SCSI_READ or SCSI_WRITE commands
* @conn: iscsi connection * @conn: iscsi connection
* @ctask: scsi command task * @ctask: scsi command ctask
* @sc: scsi command * @sc: scsi command
**/ **/
static int static int
iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask) iscsi_tcp_task_init(struct iscsi_cmd_task *ctask)
{ {
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
struct iscsi_conn *conn = ctask->conn; struct iscsi_conn *conn = ctask->conn;
struct scsi_cmnd *sc = ctask->sc; struct scsi_cmnd *sc = ctask->sc;
int err; int err;
if (!sc) {
/*
* mgmt ctasks do not have a scatterlist since they come
* in from the iscsi interface.
*/
debug_scsi("mctask deq [cid %d itt 0x%x]\n", conn->id,
ctask->itt);
/* Prepare PDU, optionally w/ immediate data */
iscsi_tcp_send_hdr_prep(conn, ctask->hdr, sizeof(*ctask->hdr));
/* If we have immediate data, attach a payload */
if (ctask->data_count)
iscsi_tcp_send_linear_data_prepare(conn, ctask->data,
ctask->data_count);
return 0;
}
BUG_ON(__kfifo_len(tcp_ctask->r2tqueue)); BUG_ON(__kfifo_len(tcp_ctask->r2tqueue));
tcp_ctask->sent = 0; tcp_ctask->sent = 0;
tcp_ctask->exp_datasn = 0; tcp_ctask->exp_datasn = 0;
...@@ -1353,52 +1379,21 @@ iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask) ...@@ -1353,52 +1379,21 @@ iscsi_tcp_ctask_init(struct iscsi_cmd_task *ctask)
return 0; return 0;
} }
/**
* iscsi_tcp_mtask_xmit - xmit management(immediate) task
* @conn: iscsi connection
* @mtask: task management task
*
* Notes:
* The function can return -EAGAIN in which case caller must
* call it again later, or recover. '0' return code means successful
* xmit.
**/
static int
iscsi_tcp_mtask_xmit(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
{
int rc;
/* Flush any pending data first. */
rc = iscsi_tcp_flush(conn);
if (rc < 0)
return rc;
if (mtask->hdr->itt == RESERVED_ITT) {
struct iscsi_session *session = conn->session;
spin_lock_bh(&session->lock);
iscsi_free_mgmt_task(conn, mtask);
spin_unlock_bh(&session->lock);
}
return 0;
}
/* /*
* iscsi_tcp_ctask_xmit - xmit normal PDU task * iscsi_tcp_task_xmit - xmit normal PDU ctask
* @conn: iscsi connection * @ctask: iscsi command ctask
* @ctask: iscsi command task
* *
* We're expected to return 0 when everything was transmitted succesfully, * We're expected to return 0 when everything was transmitted succesfully,
* -EAGAIN if there's still data in the queue, or != 0 for any other kind * -EAGAIN if there's still data in the queue, or != 0 for any other kind
* of error. * of error.
*/ */
static int static int
iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) iscsi_tcp_task_xmit(struct iscsi_cmd_task *ctask)
{ {
struct iscsi_conn *conn = ctask->conn;
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
struct scsi_cmnd *sc = ctask->sc; struct scsi_cmnd *sc = ctask->sc;
struct scsi_data_buffer *sdb = scsi_out(sc); struct scsi_data_buffer *sdb;
int rc = 0; int rc = 0;
flush: flush:
...@@ -1407,10 +1402,18 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) ...@@ -1407,10 +1402,18 @@ iscsi_tcp_ctask_xmit(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
if (rc < 0) if (rc < 0)
return rc; return rc;
/* mgmt command */
if (!sc) {
if (ctask->hdr->itt == RESERVED_ITT)
iscsi_put_ctask(ctask);
return 0;
}
/* Are we done already? */ /* Are we done already? */
if (sc->sc_data_direction != DMA_TO_DEVICE) if (sc->sc_data_direction != DMA_TO_DEVICE)
return 0; return 0;
sdb = scsi_out(sc);
if (ctask->unsol_count != 0) { if (ctask->unsol_count != 0) {
struct iscsi_data *hdr = &tcp_ctask->unsol_dtask.hdr; struct iscsi_data *hdr = &tcp_ctask->unsol_dtask.hdr;
...@@ -1688,21 +1691,6 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session, ...@@ -1688,21 +1691,6 @@ iscsi_tcp_conn_bind(struct iscsi_cls_session *cls_session,
return err; return err;
} }
/* called with host lock */
static void
iscsi_tcp_mtask_init(struct iscsi_conn *conn, struct iscsi_mgmt_task *mtask)
{
debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id, mtask->itt);
/* Prepare PDU, optionally w/ immediate data */
iscsi_tcp_send_hdr_prep(conn, mtask->hdr, sizeof(*mtask->hdr));
/* If we have immediate data, attach a payload */
if (mtask->data_count)
iscsi_tcp_send_linear_data_prepare(conn, mtask->data,
mtask->data_count);
}
static int static int
iscsi_r2tpool_alloc(struct iscsi_session *session) iscsi_r2tpool_alloc(struct iscsi_session *session)
{ {
...@@ -1710,7 +1698,7 @@ iscsi_r2tpool_alloc(struct iscsi_session *session) ...@@ -1710,7 +1698,7 @@ iscsi_r2tpool_alloc(struct iscsi_session *session)
int cmd_i; int cmd_i;
/* /*
* initialize per-task: R2T pool and xmit queue * initialize per-ctask: R2T pool and xmit queue
*/ */
for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
...@@ -1880,13 +1868,12 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, ...@@ -1880,13 +1868,12 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
cls_session = iscsi_session_setup(&iscsi_tcp_transport, shost, cmds_max, cls_session = iscsi_session_setup(&iscsi_tcp_transport, shost, cmds_max,
sizeof(struct iscsi_tcp_cmd_task), sizeof(struct iscsi_tcp_cmd_task),
sizeof(struct iscsi_tcp_mgmt_task),
initial_cmdsn); initial_cmdsn);
if (!cls_session) if (!cls_session)
goto remove_host; goto remove_host;
session = cls_session->dd_data; session = cls_session->dd_data;
shost->can_queue = session->cmds_max; shost->can_queue = session->scsi_cmds_max;
for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) {
struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; struct iscsi_cmd_task *ctask = session->cmds[cmd_i];
struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data; struct iscsi_tcp_cmd_task *tcp_ctask = ctask->dd_data;
...@@ -1895,13 +1882,6 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max, ...@@ -1895,13 +1882,6 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
ctask->hdr_max = sizeof(tcp_ctask->hdr) - ISCSI_DIGEST_SIZE; ctask->hdr_max = sizeof(tcp_ctask->hdr) - ISCSI_DIGEST_SIZE;
} }
for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) {
struct iscsi_mgmt_task *mtask = session->mgmt_cmds[cmd_i];
struct iscsi_tcp_mgmt_task *tcp_mtask = mtask->dd_data;
mtask->hdr = (struct iscsi_hdr *) &tcp_mtask->hdr;
}
if (iscsi_r2tpool_alloc(session)) if (iscsi_r2tpool_alloc(session))
goto remove_session; goto remove_session;
return cls_session; return cls_session;
...@@ -1999,11 +1979,9 @@ static struct iscsi_transport iscsi_tcp_transport = { ...@@ -1999,11 +1979,9 @@ static struct iscsi_transport iscsi_tcp_transport = {
/* IO */ /* IO */
.send_pdu = iscsi_conn_send_pdu, .send_pdu = iscsi_conn_send_pdu,
.get_stats = iscsi_conn_get_stats, .get_stats = iscsi_conn_get_stats,
.init_cmd_task = iscsi_tcp_ctask_init, .init_task = iscsi_tcp_task_init,
.init_mgmt_task = iscsi_tcp_mtask_init, .xmit_task = iscsi_tcp_task_xmit,
.xmit_cmd_task = iscsi_tcp_ctask_xmit, .cleanup_task = iscsi_tcp_cleanup_task,
.xmit_mgmt_task = iscsi_tcp_mtask_xmit,
.cleanup_cmd_task = iscsi_tcp_cleanup_ctask,
/* recovery */ /* recovery */
.session_recovery_timedout = iscsi_session_recovery_timedout, .session_recovery_timedout = iscsi_session_recovery_timedout,
}; };
......
...@@ -103,11 +103,6 @@ struct iscsi_data_task { ...@@ -103,11 +103,6 @@ struct iscsi_data_task {
char hdrext[ISCSI_DIGEST_SIZE];/* Header-Digest */ char hdrext[ISCSI_DIGEST_SIZE];/* Header-Digest */
}; };
struct iscsi_tcp_mgmt_task {
struct iscsi_hdr hdr;
char hdrext[ISCSI_DIGEST_SIZE]; /* Header-Digest */
};
struct iscsi_r2t_info { struct iscsi_r2t_info {
__be32 ttt; /* copied from R2T */ __be32 ttt; /* copied from R2T */
__be32 exp_statsn; /* copied from R2T */ __be32 exp_statsn; /* copied from R2T */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment