[SCSI] iscsi_tcp: convert iscsi_tcp to support merged tasks
Convert iscsi_tcp to support merged tasks. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
parent
3e5c28ad03
commit
fbc514b4e2
|
@ -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)
|
||||||
/**
|
/**
|
||||||
* 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)
|
||||||
/**
|
/**
|
||||||
* 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,
|
||||||
/**
|
/**
|
||||||
* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
/* 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,
|
||||||
/**
|
/**
|
||||||
* 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,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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)
|
||||||
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 @@ flush:
|
||||||
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 @@ free_socket:
|
||||||
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)
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
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 = {
|
||||||
/* 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 {
|
||||||
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 */
|
||||||
|
|
Loading…
Reference in New Issue