mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
iscsi-target: Refactor TX queue logic + export response PDU creation
This patch refactors TX immediate + response queue handling to use the new iscsit_transport API callers, and exports the necessary traditional iscsi PDU response creation functions for iser-target to utilize. This includes: - Add iscsit_build_datain_pdu() for DATAIN PDU init + convert iscsit_build_datain_pdu() - Add iscsit_build_logout_rsp() for LOGOUT_RSP PDU init + convert iscsit_send_logout() - Add iscsit_build_nopin_rsp() for NOPIN_RSP PDU init + convert iscsit_send_nopin() - Add iscsit_build_rsp_pdu() for SCSI_RSP PDU init + convert iscsit_send_response() - Add iscsit_build_task_mgt_rsp for TM_RSP PDU init + convert iscsit_send_task_mgt_rsp() - Refactor immediate queue state switch into iscsit_immediate_queue() - Convert handle_immediate_queue() to use iscsit_transport caller - Refactor response queue state switch into iscsit_response_queue() - Convert handle_response_queue to use iscsit_transport caller - Export iscsit_logout_post_handler(), iscsit_increment_maxcmdsn() and iscsit_tmr_post_handler() for external transport module usage v5 changes: - Fix solicited NopIN handling with RDMAExtensions=No (nab) v3 changes: - Add iscsit_build_reject for REJECT PDU init + convert iscsit_send_reject() v2 changes: - Add iscsit_queue_rsp() for iscsit_transport->iscsit_queue_data_in() and iscsit_transport->iscsit_queue_status() - Update lio_queue_data_in() to use ->iscsit_queue_data_in() - Update lio_queue_status() to use ->iscsit_queue_status() - Use mutex_trylock() in iscsit_increment_maxcmdsn() Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
This commit is contained in:
parent
3e1c81a95f
commit
2ec5a8c118
4 changed files with 374 additions and 308 deletions
|
@ -70,8 +70,7 @@ struct kmem_cache *lio_ooo_cache;
|
||||||
struct kmem_cache *lio_r2t_cache;
|
struct kmem_cache *lio_r2t_cache;
|
||||||
|
|
||||||
static int iscsit_handle_immediate_data(struct iscsi_cmd *,
|
static int iscsit_handle_immediate_data(struct iscsi_cmd *,
|
||||||
unsigned char *buf, u32);
|
struct iscsi_scsi_req *, u32);
|
||||||
static int iscsit_logout_post_handler(struct iscsi_cmd *, struct iscsi_conn *);
|
|
||||||
|
|
||||||
struct iscsi_tiqn *iscsit_get_tiqn_for_login(unsigned char *buf)
|
struct iscsi_tiqn *iscsit_get_tiqn_for_login(unsigned char *buf)
|
||||||
{
|
{
|
||||||
|
@ -482,6 +481,15 @@ int iscsit_del_np(struct iscsi_np *np)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int iscsit_immediate_queue(struct iscsi_conn *, struct iscsi_cmd *, int);
|
||||||
|
static int iscsit_response_queue(struct iscsi_conn *, struct iscsi_cmd *, int);
|
||||||
|
|
||||||
|
static int iscsit_queue_rsp(struct iscsi_conn *conn, struct iscsi_cmd *cmd)
|
||||||
|
{
|
||||||
|
iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static struct iscsit_transport iscsi_target_transport = {
|
static struct iscsit_transport iscsi_target_transport = {
|
||||||
.name = "iSCSI/TCP",
|
.name = "iSCSI/TCP",
|
||||||
.transport_type = ISCSI_TCP,
|
.transport_type = ISCSI_TCP,
|
||||||
|
@ -493,6 +501,10 @@ static struct iscsit_transport iscsi_target_transport = {
|
||||||
.iscsit_get_login_rx = iscsit_get_login_rx,
|
.iscsit_get_login_rx = iscsit_get_login_rx,
|
||||||
.iscsit_put_login_tx = iscsit_put_login_tx,
|
.iscsit_put_login_tx = iscsit_put_login_tx,
|
||||||
.iscsit_get_dataout = iscsit_build_r2ts_for_cmd,
|
.iscsit_get_dataout = iscsit_build_r2ts_for_cmd,
|
||||||
|
.iscsit_immediate_queue = iscsit_immediate_queue,
|
||||||
|
.iscsit_response_queue = iscsit_response_queue,
|
||||||
|
.iscsit_queue_data_in = iscsit_queue_rsp,
|
||||||
|
.iscsit_queue_status = iscsit_queue_rsp,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init iscsi_target_init_module(void)
|
static int __init iscsi_target_init_module(void)
|
||||||
|
@ -651,14 +663,6 @@ static int iscsit_add_reject(
|
||||||
iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
|
iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
|
||||||
|
|
||||||
ret = wait_for_completion_interruptible(&cmd->reject_comp);
|
ret = wait_for_completion_interruptible(&cmd->reject_comp);
|
||||||
/*
|
|
||||||
* Perform the kref_put now if se_cmd has been setup by
|
|
||||||
* iscsit_setup_scsi_cmd()
|
|
||||||
*/
|
|
||||||
if (cmd->se_cmd.se_tfo != NULL) {
|
|
||||||
pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n");
|
|
||||||
target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
|
|
||||||
}
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -2549,18 +2553,60 @@ static void iscsit_tx_thread_wait_for_tcp(struct iscsi_conn *conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iscsit_send_data_in(
|
static void
|
||||||
struct iscsi_cmd *cmd,
|
iscsit_build_datain_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||||
struct iscsi_conn *conn)
|
struct iscsi_datain *datain, struct iscsi_data_rsp *hdr,
|
||||||
|
bool set_statsn)
|
||||||
{
|
{
|
||||||
int iov_ret = 0, set_statsn = 0;
|
hdr->opcode = ISCSI_OP_SCSI_DATA_IN;
|
||||||
u32 iov_count = 0, tx_size = 0;
|
hdr->flags = datain->flags;
|
||||||
|
if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
|
||||||
|
if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
|
||||||
|
hdr->flags |= ISCSI_FLAG_DATA_OVERFLOW;
|
||||||
|
hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
|
||||||
|
} else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
|
||||||
|
hdr->flags |= ISCSI_FLAG_DATA_UNDERFLOW;
|
||||||
|
hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hton24(hdr->dlength, datain->length);
|
||||||
|
if (hdr->flags & ISCSI_FLAG_DATA_ACK)
|
||||||
|
int_to_scsilun(cmd->se_cmd.orig_fe_lun,
|
||||||
|
(struct scsi_lun *)&hdr->lun);
|
||||||
|
else
|
||||||
|
put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
|
||||||
|
|
||||||
|
hdr->itt = cmd->init_task_tag;
|
||||||
|
|
||||||
|
if (hdr->flags & ISCSI_FLAG_DATA_ACK)
|
||||||
|
hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag);
|
||||||
|
else
|
||||||
|
hdr->ttt = cpu_to_be32(0xFFFFFFFF);
|
||||||
|
if (set_statsn)
|
||||||
|
hdr->statsn = cpu_to_be32(cmd->stat_sn);
|
||||||
|
else
|
||||||
|
hdr->statsn = cpu_to_be32(0xFFFFFFFF);
|
||||||
|
|
||||||
|
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
||||||
|
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
||||||
|
hdr->datasn = cpu_to_be32(datain->data_sn);
|
||||||
|
hdr->offset = cpu_to_be32(datain->offset);
|
||||||
|
|
||||||
|
pr_debug("Built DataIN ITT: 0x%08x, StatSN: 0x%08x,"
|
||||||
|
" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
|
||||||
|
cmd->init_task_tag, ntohl(hdr->statsn), ntohl(hdr->datasn),
|
||||||
|
ntohl(hdr->offset), datain->length, conn->cid);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iscsit_send_datain(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
|
||||||
|
{
|
||||||
|
struct iscsi_data_rsp *hdr = (struct iscsi_data_rsp *)&cmd->pdu[0];
|
||||||
struct iscsi_datain datain;
|
struct iscsi_datain datain;
|
||||||
struct iscsi_datain_req *dr;
|
struct iscsi_datain_req *dr;
|
||||||
struct iscsi_data_rsp *hdr;
|
|
||||||
struct kvec *iov;
|
struct kvec *iov;
|
||||||
int eodr = 0;
|
u32 iov_count = 0, tx_size = 0;
|
||||||
int ret;
|
int eodr = 0, ret, iov_ret;
|
||||||
|
bool set_statsn = false;
|
||||||
|
|
||||||
memset(&datain, 0, sizeof(struct iscsi_datain));
|
memset(&datain, 0, sizeof(struct iscsi_datain));
|
||||||
dr = iscsit_get_datain_values(cmd, &datain);
|
dr = iscsit_get_datain_values(cmd, &datain);
|
||||||
|
@ -2569,7 +2615,6 @@ static int iscsit_send_data_in(
|
||||||
cmd->init_task_tag);
|
cmd->init_task_tag);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Be paranoid and double check the logic for now.
|
* Be paranoid and double check the logic for now.
|
||||||
*/
|
*/
|
||||||
|
@ -2577,7 +2622,7 @@ static int iscsit_send_data_in(
|
||||||
pr_err("Command ITT: 0x%08x, datain.offset: %u and"
|
pr_err("Command ITT: 0x%08x, datain.offset: %u and"
|
||||||
" datain.length: %u exceeds cmd->data_length: %u\n",
|
" datain.length: %u exceeds cmd->data_length: %u\n",
|
||||||
cmd->init_task_tag, datain.offset, datain.length,
|
cmd->init_task_tag, datain.offset, datain.length,
|
||||||
cmd->se_cmd.data_length);
|
cmd->se_cmd.data_length);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2601,47 +2646,13 @@ static int iscsit_send_data_in(
|
||||||
(dr->dr_complete == DATAIN_COMPLETE_CONNECTION_RECOVERY)) {
|
(dr->dr_complete == DATAIN_COMPLETE_CONNECTION_RECOVERY)) {
|
||||||
iscsit_increment_maxcmdsn(cmd, conn->sess);
|
iscsit_increment_maxcmdsn(cmd, conn->sess);
|
||||||
cmd->stat_sn = conn->stat_sn++;
|
cmd->stat_sn = conn->stat_sn++;
|
||||||
set_statsn = 1;
|
set_statsn = true;
|
||||||
} else if (dr->dr_complete ==
|
} else if (dr->dr_complete ==
|
||||||
DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY)
|
DATAIN_COMPLETE_WITHIN_COMMAND_RECOVERY)
|
||||||
set_statsn = 1;
|
set_statsn = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
hdr = (struct iscsi_data_rsp *) cmd->pdu;
|
iscsit_build_datain_pdu(cmd, conn, &datain, hdr, set_statsn);
|
||||||
memset(hdr, 0, ISCSI_HDR_LEN);
|
|
||||||
hdr->opcode = ISCSI_OP_SCSI_DATA_IN;
|
|
||||||
hdr->flags = datain.flags;
|
|
||||||
if (hdr->flags & ISCSI_FLAG_DATA_STATUS) {
|
|
||||||
if (cmd->se_cmd.se_cmd_flags & SCF_OVERFLOW_BIT) {
|
|
||||||
hdr->flags |= ISCSI_FLAG_DATA_OVERFLOW;
|
|
||||||
hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
|
|
||||||
} else if (cmd->se_cmd.se_cmd_flags & SCF_UNDERFLOW_BIT) {
|
|
||||||
hdr->flags |= ISCSI_FLAG_DATA_UNDERFLOW;
|
|
||||||
hdr->residual_count = cpu_to_be32(cmd->se_cmd.residual_count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
hton24(hdr->dlength, datain.length);
|
|
||||||
if (hdr->flags & ISCSI_FLAG_DATA_ACK)
|
|
||||||
int_to_scsilun(cmd->se_cmd.orig_fe_lun,
|
|
||||||
(struct scsi_lun *)&hdr->lun);
|
|
||||||
else
|
|
||||||
put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
|
|
||||||
|
|
||||||
hdr->itt = cmd->init_task_tag;
|
|
||||||
|
|
||||||
if (hdr->flags & ISCSI_FLAG_DATA_ACK)
|
|
||||||
hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag);
|
|
||||||
else
|
|
||||||
hdr->ttt = cpu_to_be32(0xFFFFFFFF);
|
|
||||||
if (set_statsn)
|
|
||||||
hdr->statsn = cpu_to_be32(cmd->stat_sn);
|
|
||||||
else
|
|
||||||
hdr->statsn = cpu_to_be32(0xFFFFFFFF);
|
|
||||||
|
|
||||||
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
|
||||||
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
|
||||||
hdr->datasn = cpu_to_be32(datain.data_sn);
|
|
||||||
hdr->offset = cpu_to_be32(datain.offset);
|
|
||||||
|
|
||||||
iov = &cmd->iov_data[0];
|
iov = &cmd->iov_data[0];
|
||||||
iov[iov_count].iov_base = cmd->pdu;
|
iov[iov_count].iov_base = cmd->pdu;
|
||||||
|
@ -2652,7 +2663,7 @@ static int iscsit_send_data_in(
|
||||||
u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
|
u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
|
||||||
|
|
||||||
iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
|
iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
|
||||||
(unsigned char *)hdr, ISCSI_HDR_LEN,
|
(unsigned char *)cmd->pdu, ISCSI_HDR_LEN,
|
||||||
0, NULL, (u8 *)header_digest);
|
0, NULL, (u8 *)header_digest);
|
||||||
|
|
||||||
iov[0].iov_len += ISCSI_CRC_LEN;
|
iov[0].iov_len += ISCSI_CRC_LEN;
|
||||||
|
@ -2662,7 +2673,8 @@ static int iscsit_send_data_in(
|
||||||
" for DataIN PDU 0x%08x\n", *header_digest);
|
" for DataIN PDU 0x%08x\n", *header_digest);
|
||||||
}
|
}
|
||||||
|
|
||||||
iov_ret = iscsit_map_iovec(cmd, &cmd->iov_data[1], datain.offset, datain.length);
|
iov_ret = iscsit_map_iovec(cmd, &cmd->iov_data[1],
|
||||||
|
datain.offset, datain.length);
|
||||||
if (iov_ret < 0)
|
if (iov_ret < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -2693,11 +2705,6 @@ static int iscsit_send_data_in(
|
||||||
cmd->iov_data_count = iov_count;
|
cmd->iov_data_count = iov_count;
|
||||||
cmd->tx_size = tx_size;
|
cmd->tx_size = tx_size;
|
||||||
|
|
||||||
pr_debug("Built DataIN ITT: 0x%08x, StatSN: 0x%08x,"
|
|
||||||
" DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
|
|
||||||
cmd->init_task_tag, ntohl(hdr->statsn), ntohl(hdr->datasn),
|
|
||||||
ntohl(hdr->offset), datain.length, conn->cid);
|
|
||||||
|
|
||||||
/* sendpage is preferred but can't insert markers */
|
/* sendpage is preferred but can't insert markers */
|
||||||
if (!conn->conn_ops->IFMarker)
|
if (!conn->conn_ops->IFMarker)
|
||||||
ret = iscsit_fe_sendpage_sg(cmd, conn);
|
ret = iscsit_fe_sendpage_sg(cmd, conn);
|
||||||
|
@ -2720,16 +2727,13 @@ static int iscsit_send_data_in(
|
||||||
return eodr;
|
return eodr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iscsit_send_logout_response(
|
int
|
||||||
struct iscsi_cmd *cmd,
|
iscsit_build_logout_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||||
struct iscsi_conn *conn)
|
struct iscsi_logout_rsp *hdr)
|
||||||
{
|
{
|
||||||
int niov = 0, tx_size;
|
|
||||||
struct iscsi_conn *logout_conn = NULL;
|
struct iscsi_conn *logout_conn = NULL;
|
||||||
struct iscsi_conn_recovery *cr = NULL;
|
struct iscsi_conn_recovery *cr = NULL;
|
||||||
struct iscsi_session *sess = conn->sess;
|
struct iscsi_session *sess = conn->sess;
|
||||||
struct kvec *iov;
|
|
||||||
struct iscsi_logout_rsp *hdr;
|
|
||||||
/*
|
/*
|
||||||
* The actual shutting down of Sessions and/or Connections
|
* The actual shutting down of Sessions and/or Connections
|
||||||
* for CLOSESESSION and CLOSECONNECTION Logout Requests
|
* for CLOSESESSION and CLOSECONNECTION Logout Requests
|
||||||
|
@ -2798,9 +2802,6 @@ static int iscsit_send_logout_response(
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tx_size = ISCSI_HDR_LEN;
|
|
||||||
hdr = (struct iscsi_logout_rsp *)cmd->pdu;
|
|
||||||
memset(hdr, 0, ISCSI_HDR_LEN);
|
|
||||||
hdr->opcode = ISCSI_OP_LOGOUT_RSP;
|
hdr->opcode = ISCSI_OP_LOGOUT_RSP;
|
||||||
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
|
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
|
||||||
hdr->response = cmd->logout_response;
|
hdr->response = cmd->logout_response;
|
||||||
|
@ -2812,6 +2813,27 @@ static int iscsit_send_logout_response(
|
||||||
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
||||||
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
||||||
|
|
||||||
|
pr_debug("Built Logout Response ITT: 0x%08x StatSN:"
|
||||||
|
" 0x%08x Response: 0x%02x CID: %hu on CID: %hu\n",
|
||||||
|
cmd->init_task_tag, cmd->stat_sn, hdr->response,
|
||||||
|
cmd->logout_cid, conn->cid);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(iscsit_build_logout_rsp);
|
||||||
|
|
||||||
|
static int
|
||||||
|
iscsit_send_logout(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
|
||||||
|
{
|
||||||
|
struct kvec *iov;
|
||||||
|
int niov = 0, tx_size, rc;
|
||||||
|
|
||||||
|
rc = iscsit_build_logout_rsp(cmd, conn,
|
||||||
|
(struct iscsi_logout_rsp *)&cmd->pdu[0]);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
tx_size = ISCSI_HDR_LEN;
|
||||||
iov = &cmd->iov_misc[0];
|
iov = &cmd->iov_misc[0];
|
||||||
iov[niov].iov_base = cmd->pdu;
|
iov[niov].iov_base = cmd->pdu;
|
||||||
iov[niov++].iov_len = ISCSI_HDR_LEN;
|
iov[niov++].iov_len = ISCSI_HDR_LEN;
|
||||||
|
@ -2820,7 +2842,7 @@ static int iscsit_send_logout_response(
|
||||||
u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
|
u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
|
||||||
|
|
||||||
iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
|
iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
|
||||||
(unsigned char *)hdr, ISCSI_HDR_LEN,
|
(unsigned char *)&cmd->pdu[0], ISCSI_HDR_LEN,
|
||||||
0, NULL, (u8 *)header_digest);
|
0, NULL, (u8 *)header_digest);
|
||||||
|
|
||||||
iov[0].iov_len += ISCSI_CRC_LEN;
|
iov[0].iov_len += ISCSI_CRC_LEN;
|
||||||
|
@ -2831,14 +2853,37 @@ static int iscsit_send_logout_response(
|
||||||
cmd->iov_misc_count = niov;
|
cmd->iov_misc_count = niov;
|
||||||
cmd->tx_size = tx_size;
|
cmd->tx_size = tx_size;
|
||||||
|
|
||||||
pr_debug("Sending Logout Response ITT: 0x%08x StatSN:"
|
|
||||||
" 0x%08x Response: 0x%02x CID: %hu on CID: %hu\n",
|
|
||||||
cmd->init_task_tag, cmd->stat_sn, hdr->response,
|
|
||||||
cmd->logout_cid, conn->cid);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
iscsit_build_nopin_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||||
|
struct iscsi_nopin *hdr, bool nopout_response)
|
||||||
|
{
|
||||||
|
hdr->opcode = ISCSI_OP_NOOP_IN;
|
||||||
|
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
|
||||||
|
hton24(hdr->dlength, cmd->buf_ptr_size);
|
||||||
|
if (nopout_response)
|
||||||
|
put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
|
||||||
|
hdr->itt = cmd->init_task_tag;
|
||||||
|
hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag);
|
||||||
|
cmd->stat_sn = (nopout_response) ? conn->stat_sn++ :
|
||||||
|
conn->stat_sn;
|
||||||
|
hdr->statsn = cpu_to_be32(cmd->stat_sn);
|
||||||
|
|
||||||
|
if (nopout_response)
|
||||||
|
iscsit_increment_maxcmdsn(cmd, conn->sess);
|
||||||
|
|
||||||
|
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
||||||
|
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
||||||
|
|
||||||
|
pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x,"
|
||||||
|
" StatSN: 0x%08x, Length %u\n", (nopout_response) ?
|
||||||
|
"Solicitied" : "Unsolicitied", cmd->init_task_tag,
|
||||||
|
cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(iscsit_build_nopin_rsp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unsolicited NOPIN, either requesting a response or not.
|
* Unsolicited NOPIN, either requesting a response or not.
|
||||||
*/
|
*/
|
||||||
|
@ -2847,20 +2892,10 @@ static int iscsit_send_unsolicited_nopin(
|
||||||
struct iscsi_conn *conn,
|
struct iscsi_conn *conn,
|
||||||
int want_response)
|
int want_response)
|
||||||
{
|
{
|
||||||
int tx_size = ISCSI_HDR_LEN;
|
struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0];
|
||||||
struct iscsi_nopin *hdr;
|
int tx_size = ISCSI_HDR_LEN, ret;
|
||||||
int ret;
|
|
||||||
|
|
||||||
hdr = (struct iscsi_nopin *) cmd->pdu;
|
iscsit_build_nopin_rsp(cmd, conn, hdr, false);
|
||||||
memset(hdr, 0, ISCSI_HDR_LEN);
|
|
||||||
hdr->opcode = ISCSI_OP_NOOP_IN;
|
|
||||||
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
|
|
||||||
hdr->itt = cmd->init_task_tag;
|
|
||||||
hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag);
|
|
||||||
cmd->stat_sn = conn->stat_sn;
|
|
||||||
hdr->statsn = cpu_to_be32(cmd->stat_sn);
|
|
||||||
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
|
||||||
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
|
||||||
|
|
||||||
if (conn->conn_ops->HeaderDigest) {
|
if (conn->conn_ops->HeaderDigest) {
|
||||||
u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
|
u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
|
||||||
|
@ -2896,31 +2931,17 @@ static int iscsit_send_unsolicited_nopin(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iscsit_send_nopin_response(
|
static int
|
||||||
struct iscsi_cmd *cmd,
|
iscsit_send_nopin(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
|
||||||
struct iscsi_conn *conn)
|
|
||||||
{
|
{
|
||||||
int niov = 0, tx_size;
|
struct iscsi_nopin *hdr = (struct iscsi_nopin *)&cmd->pdu[0];
|
||||||
u32 padding = 0;
|
|
||||||
struct kvec *iov;
|
struct kvec *iov;
|
||||||
struct iscsi_nopin *hdr;
|
u32 padding = 0;
|
||||||
|
int niov = 0, tx_size;
|
||||||
|
|
||||||
|
iscsit_build_nopin_rsp(cmd, conn, hdr, true);
|
||||||
|
|
||||||
tx_size = ISCSI_HDR_LEN;
|
tx_size = ISCSI_HDR_LEN;
|
||||||
hdr = (struct iscsi_nopin *) cmd->pdu;
|
|
||||||
memset(hdr, 0, ISCSI_HDR_LEN);
|
|
||||||
hdr->opcode = ISCSI_OP_NOOP_IN;
|
|
||||||
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
|
|
||||||
hton24(hdr->dlength, cmd->buf_ptr_size);
|
|
||||||
put_unaligned_le64(0xFFFFFFFFFFFFFFFFULL, &hdr->lun);
|
|
||||||
hdr->itt = cmd->init_task_tag;
|
|
||||||
hdr->ttt = cpu_to_be32(cmd->targ_xfer_tag);
|
|
||||||
cmd->stat_sn = conn->stat_sn++;
|
|
||||||
hdr->statsn = cpu_to_be32(cmd->stat_sn);
|
|
||||||
|
|
||||||
iscsit_increment_maxcmdsn(cmd, conn->sess);
|
|
||||||
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
|
||||||
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
|
||||||
|
|
||||||
iov = &cmd->iov_misc[0];
|
iov = &cmd->iov_misc[0];
|
||||||
iov[niov].iov_base = cmd->pdu;
|
iov[niov].iov_base = cmd->pdu;
|
||||||
iov[niov++].iov_len = ISCSI_HDR_LEN;
|
iov[niov++].iov_len = ISCSI_HDR_LEN;
|
||||||
|
@ -2976,10 +2997,6 @@ static int iscsit_send_nopin_response(
|
||||||
cmd->iov_misc_count = niov;
|
cmd->iov_misc_count = niov;
|
||||||
cmd->tx_size = tx_size;
|
cmd->tx_size = tx_size;
|
||||||
|
|
||||||
pr_debug("Sending NOPIN Response ITT: 0x%08x, TTT:"
|
|
||||||
" 0x%08x, StatSN: 0x%08x, Length %u\n", cmd->init_task_tag,
|
|
||||||
cmd->targ_xfer_tag, cmd->stat_sn, cmd->buf_ptr_size);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3140,24 +3157,16 @@ int iscsit_build_r2ts_for_cmd(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iscsit_send_status(
|
void iscsit_build_rsp_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||||
struct iscsi_cmd *cmd,
|
bool inc_stat_sn, struct iscsi_scsi_rsp *hdr)
|
||||||
struct iscsi_conn *conn)
|
|
||||||
{
|
{
|
||||||
u8 iov_count = 0, recovery;
|
if (inc_stat_sn)
|
||||||
u32 padding = 0, tx_size = 0;
|
|
||||||
struct iscsi_scsi_rsp *hdr;
|
|
||||||
struct kvec *iov;
|
|
||||||
|
|
||||||
recovery = (cmd->i_state != ISTATE_SEND_STATUS);
|
|
||||||
if (!recovery)
|
|
||||||
cmd->stat_sn = conn->stat_sn++;
|
cmd->stat_sn = conn->stat_sn++;
|
||||||
|
|
||||||
spin_lock_bh(&conn->sess->session_stats_lock);
|
spin_lock_bh(&conn->sess->session_stats_lock);
|
||||||
conn->sess->rsp_pdus++;
|
conn->sess->rsp_pdus++;
|
||||||
spin_unlock_bh(&conn->sess->session_stats_lock);
|
spin_unlock_bh(&conn->sess->session_stats_lock);
|
||||||
|
|
||||||
hdr = (struct iscsi_scsi_rsp *) cmd->pdu;
|
|
||||||
memset(hdr, 0, ISCSI_HDR_LEN);
|
memset(hdr, 0, ISCSI_HDR_LEN);
|
||||||
hdr->opcode = ISCSI_OP_SCSI_CMD_RSP;
|
hdr->opcode = ISCSI_OP_SCSI_CMD_RSP;
|
||||||
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
|
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
|
||||||
|
@ -3177,6 +3186,23 @@ static int iscsit_send_status(
|
||||||
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
||||||
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
||||||
|
|
||||||
|
pr_debug("Built SCSI Response, ITT: 0x%08x, StatSN: 0x%08x,"
|
||||||
|
" Response: 0x%02x, SAM Status: 0x%02x, CID: %hu\n",
|
||||||
|
cmd->init_task_tag, cmd->stat_sn, cmd->se_cmd.scsi_status,
|
||||||
|
cmd->se_cmd.scsi_status, conn->cid);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(iscsit_build_rsp_pdu);
|
||||||
|
|
||||||
|
static int iscsit_send_response(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
|
||||||
|
{
|
||||||
|
struct iscsi_scsi_rsp *hdr = (struct iscsi_scsi_rsp *)&cmd->pdu[0];
|
||||||
|
struct kvec *iov;
|
||||||
|
u32 padding = 0, tx_size = 0;
|
||||||
|
int iov_count = 0;
|
||||||
|
bool inc_stat_sn = (cmd->i_state == ISTATE_SEND_STATUS);
|
||||||
|
|
||||||
|
iscsit_build_rsp_pdu(cmd, conn, inc_stat_sn, hdr);
|
||||||
|
|
||||||
iov = &cmd->iov_misc[0];
|
iov = &cmd->iov_misc[0];
|
||||||
iov[iov_count].iov_base = cmd->pdu;
|
iov[iov_count].iov_base = cmd->pdu;
|
||||||
iov[iov_count++].iov_len = ISCSI_HDR_LEN;
|
iov[iov_count++].iov_len = ISCSI_HDR_LEN;
|
||||||
|
@ -3231,7 +3257,7 @@ static int iscsit_send_status(
|
||||||
u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
|
u32 *header_digest = (u32 *)&cmd->pdu[ISCSI_HDR_LEN];
|
||||||
|
|
||||||
iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
|
iscsit_do_crypto_hash_buf(&conn->conn_tx_hash,
|
||||||
(unsigned char *)hdr, ISCSI_HDR_LEN,
|
(unsigned char *)cmd->pdu, ISCSI_HDR_LEN,
|
||||||
0, NULL, (u8 *)header_digest);
|
0, NULL, (u8 *)header_digest);
|
||||||
|
|
||||||
iov[0].iov_len += ISCSI_CRC_LEN;
|
iov[0].iov_len += ISCSI_CRC_LEN;
|
||||||
|
@ -3243,11 +3269,6 @@ static int iscsit_send_status(
|
||||||
cmd->iov_misc_count = iov_count;
|
cmd->iov_misc_count = iov_count;
|
||||||
cmd->tx_size = tx_size;
|
cmd->tx_size = tx_size;
|
||||||
|
|
||||||
pr_debug("Built %sSCSI Response, ITT: 0x%08x, StatSN: 0x%08x,"
|
|
||||||
" Response: 0x%02x, SAM Status: 0x%02x, CID: %hu\n",
|
|
||||||
(!recovery) ? "" : "Recovery ", cmd->init_task_tag,
|
|
||||||
cmd->stat_sn, 0x00, cmd->se_cmd.scsi_status, conn->cid);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3270,16 +3291,12 @@ static u8 iscsit_convert_tcm_tmr_rsp(struct se_tmr_req *se_tmr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iscsit_send_task_mgt_rsp(
|
void
|
||||||
struct iscsi_cmd *cmd,
|
iscsit_build_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||||
struct iscsi_conn *conn)
|
struct iscsi_tm_rsp *hdr)
|
||||||
{
|
{
|
||||||
struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
|
struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
|
||||||
struct iscsi_tm_rsp *hdr;
|
|
||||||
u32 tx_size = 0;
|
|
||||||
|
|
||||||
hdr = (struct iscsi_tm_rsp *) cmd->pdu;
|
|
||||||
memset(hdr, 0, ISCSI_HDR_LEN);
|
|
||||||
hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP;
|
hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP;
|
||||||
hdr->flags = ISCSI_FLAG_CMD_FINAL;
|
hdr->flags = ISCSI_FLAG_CMD_FINAL;
|
||||||
hdr->response = iscsit_convert_tcm_tmr_rsp(se_tmr);
|
hdr->response = iscsit_convert_tcm_tmr_rsp(se_tmr);
|
||||||
|
@ -3291,6 +3308,20 @@ static int iscsit_send_task_mgt_rsp(
|
||||||
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
||||||
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
||||||
|
|
||||||
|
pr_debug("Built Task Management Response ITT: 0x%08x,"
|
||||||
|
" StatSN: 0x%08x, Response: 0x%02x, CID: %hu\n",
|
||||||
|
cmd->init_task_tag, cmd->stat_sn, hdr->response, conn->cid);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(iscsit_build_task_mgt_rsp);
|
||||||
|
|
||||||
|
static int
|
||||||
|
iscsit_send_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
|
||||||
|
{
|
||||||
|
struct iscsi_tm_rsp *hdr = (struct iscsi_tm_rsp *)&cmd->pdu[0];
|
||||||
|
u32 tx_size = 0;
|
||||||
|
|
||||||
|
iscsit_build_task_mgt_rsp(cmd, conn, hdr);
|
||||||
|
|
||||||
cmd->iov_misc[0].iov_base = cmd->pdu;
|
cmd->iov_misc[0].iov_base = cmd->pdu;
|
||||||
cmd->iov_misc[0].iov_len = ISCSI_HDR_LEN;
|
cmd->iov_misc[0].iov_len = ISCSI_HDR_LEN;
|
||||||
tx_size += ISCSI_HDR_LEN;
|
tx_size += ISCSI_HDR_LEN;
|
||||||
|
@ -3311,10 +3342,6 @@ static int iscsit_send_task_mgt_rsp(
|
||||||
cmd->iov_misc_count = 1;
|
cmd->iov_misc_count = 1;
|
||||||
cmd->tx_size = tx_size;
|
cmd->tx_size = tx_size;
|
||||||
|
|
||||||
pr_debug("Built Task Management Response ITT: 0x%08x,"
|
|
||||||
" StatSN: 0x%08x, Response: 0x%02x, CID: %hu\n",
|
|
||||||
cmd->init_task_tag, cmd->stat_sn, hdr->response, conn->cid);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3510,6 +3537,22 @@ static int iscsit_send_text_rsp(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
iscsit_build_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||||
|
struct iscsi_reject *hdr)
|
||||||
|
{
|
||||||
|
hdr->opcode = ISCSI_OP_REJECT;
|
||||||
|
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
|
||||||
|
hton24(hdr->dlength, ISCSI_HDR_LEN);
|
||||||
|
hdr->ffffffff = cpu_to_be32(0xffffffff);
|
||||||
|
cmd->stat_sn = conn->stat_sn++;
|
||||||
|
hdr->statsn = cpu_to_be32(cmd->stat_sn);
|
||||||
|
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
||||||
|
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
||||||
|
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(iscsit_build_reject);
|
||||||
|
|
||||||
static int iscsit_send_reject(
|
static int iscsit_send_reject(
|
||||||
struct iscsi_cmd *cmd,
|
struct iscsi_cmd *cmd,
|
||||||
struct iscsi_conn *conn)
|
struct iscsi_conn *conn)
|
||||||
|
@ -3518,18 +3561,9 @@ static int iscsit_send_reject(
|
||||||
struct iscsi_reject *hdr;
|
struct iscsi_reject *hdr;
|
||||||
struct kvec *iov;
|
struct kvec *iov;
|
||||||
|
|
||||||
hdr = (struct iscsi_reject *) cmd->pdu;
|
iscsit_build_reject(cmd, conn, (struct iscsi_reject *)&cmd->pdu[0]);
|
||||||
hdr->opcode = ISCSI_OP_REJECT;
|
|
||||||
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
|
|
||||||
hton24(hdr->dlength, ISCSI_HDR_LEN);
|
|
||||||
hdr->ffffffff = cpu_to_be32(0xffffffff);
|
|
||||||
cmd->stat_sn = conn->stat_sn++;
|
|
||||||
hdr->statsn = cpu_to_be32(cmd->stat_sn);
|
|
||||||
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
|
||||||
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
|
||||||
|
|
||||||
iov = &cmd->iov_misc[0];
|
iov = &cmd->iov_misc[0];
|
||||||
|
|
||||||
iov[iov_count].iov_base = cmd->pdu;
|
iov[iov_count].iov_base = cmd->pdu;
|
||||||
iov[iov_count++].iov_len = ISCSI_HDR_LEN;
|
iov[iov_count++].iov_len = ISCSI_HDR_LEN;
|
||||||
iov[iov_count].iov_base = cmd->buf_ptr;
|
iov[iov_count].iov_base = cmd->buf_ptr;
|
||||||
|
@ -3626,8 +3660,53 @@ static inline void iscsit_thread_check_cpumask(
|
||||||
set_cpus_allowed_ptr(p, conn->conn_cpumask);
|
set_cpus_allowed_ptr(p, conn->conn_cpumask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_immediate_queue(struct iscsi_conn *conn)
|
static int
|
||||||
|
iscsit_immediate_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case ISTATE_SEND_R2T:
|
||||||
|
ret = iscsit_send_r2t(cmd, conn);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
break;
|
||||||
|
case ISTATE_REMOVE:
|
||||||
|
spin_lock_bh(&conn->cmd_lock);
|
||||||
|
list_del(&cmd->i_conn_node);
|
||||||
|
spin_unlock_bh(&conn->cmd_lock);
|
||||||
|
|
||||||
|
iscsit_free_cmd(cmd);
|
||||||
|
break;
|
||||||
|
case ISTATE_SEND_NOPIN_WANT_RESPONSE:
|
||||||
|
iscsit_mod_nopin_response_timer(conn);
|
||||||
|
ret = iscsit_send_unsolicited_nopin(cmd, conn, 1);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
break;
|
||||||
|
case ISTATE_SEND_NOPIN_NO_RESPONSE:
|
||||||
|
ret = iscsit_send_unsolicited_nopin(cmd, conn, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_err("Unknown Opcode: 0x%02x ITT:"
|
||||||
|
" 0x%08x, i_state: %d on CID: %hu\n",
|
||||||
|
cmd->iscsi_opcode, cmd->init_task_tag, state,
|
||||||
|
conn->cid);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
iscsit_handle_immediate_queue(struct iscsi_conn *conn)
|
||||||
|
{
|
||||||
|
struct iscsit_transport *t = conn->conn_transport;
|
||||||
struct iscsi_queue_req *qr;
|
struct iscsi_queue_req *qr;
|
||||||
struct iscsi_cmd *cmd;
|
struct iscsi_cmd *cmd;
|
||||||
u8 state;
|
u8 state;
|
||||||
|
@ -3639,52 +3718,139 @@ static int handle_immediate_queue(struct iscsi_conn *conn)
|
||||||
state = qr->state;
|
state = qr->state;
|
||||||
kmem_cache_free(lio_qr_cache, qr);
|
kmem_cache_free(lio_qr_cache, qr);
|
||||||
|
|
||||||
switch (state) {
|
ret = t->iscsit_immediate_queue(conn, cmd, state);
|
||||||
case ISTATE_SEND_R2T:
|
if (ret < 0)
|
||||||
ret = iscsit_send_r2t(cmd, conn);
|
return ret;
|
||||||
if (ret < 0)
|
}
|
||||||
goto err;
|
|
||||||
break;
|
|
||||||
case ISTATE_REMOVE:
|
|
||||||
if (cmd->data_direction == DMA_TO_DEVICE)
|
|
||||||
iscsit_stop_dataout_timer(cmd);
|
|
||||||
|
|
||||||
spin_lock_bh(&conn->cmd_lock);
|
return 0;
|
||||||
list_del(&cmd->i_conn_node);
|
}
|
||||||
spin_unlock_bh(&conn->cmd_lock);
|
|
||||||
|
|
||||||
iscsit_free_cmd(cmd);
|
static int
|
||||||
continue;
|
iscsit_response_queue(struct iscsi_conn *conn, struct iscsi_cmd *cmd, int state)
|
||||||
case ISTATE_SEND_NOPIN_WANT_RESPONSE:
|
{
|
||||||
iscsit_mod_nopin_response_timer(conn);
|
int ret;
|
||||||
ret = iscsit_send_unsolicited_nopin(cmd,
|
|
||||||
conn, 1);
|
check_rsp_state:
|
||||||
if (ret < 0)
|
switch (state) {
|
||||||
goto err;
|
case ISTATE_SEND_DATAIN:
|
||||||
|
ret = iscsit_send_datain(cmd, conn);
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
else if (!ret)
|
||||||
|
/* more drs */
|
||||||
|
goto check_rsp_state;
|
||||||
|
else if (ret == 1) {
|
||||||
|
/* all done */
|
||||||
|
spin_lock_bh(&cmd->istate_lock);
|
||||||
|
cmd->i_state = ISTATE_SENT_STATUS;
|
||||||
|
spin_unlock_bh(&cmd->istate_lock);
|
||||||
|
|
||||||
|
if (atomic_read(&conn->check_immediate_queue))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} else if (ret == 2) {
|
||||||
|
/* Still must send status,
|
||||||
|
SCF_TRANSPORT_TASK_SENSE was set */
|
||||||
|
spin_lock_bh(&cmd->istate_lock);
|
||||||
|
cmd->i_state = ISTATE_SEND_STATUS;
|
||||||
|
spin_unlock_bh(&cmd->istate_lock);
|
||||||
|
state = ISTATE_SEND_STATUS;
|
||||||
|
goto check_rsp_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
case ISTATE_SEND_STATUS:
|
||||||
|
case ISTATE_SEND_STATUS_RECOVERY:
|
||||||
|
ret = iscsit_send_response(cmd, conn);
|
||||||
|
break;
|
||||||
|
case ISTATE_SEND_LOGOUTRSP:
|
||||||
|
ret = iscsit_send_logout(cmd, conn);
|
||||||
|
break;
|
||||||
|
case ISTATE_SEND_ASYNCMSG:
|
||||||
|
ret = iscsit_send_conn_drop_async_message(
|
||||||
|
cmd, conn);
|
||||||
|
break;
|
||||||
|
case ISTATE_SEND_NOPIN:
|
||||||
|
ret = iscsit_send_nopin(cmd, conn);
|
||||||
|
break;
|
||||||
|
case ISTATE_SEND_REJECT:
|
||||||
|
ret = iscsit_send_reject(cmd, conn);
|
||||||
|
break;
|
||||||
|
case ISTATE_SEND_TASKMGTRSP:
|
||||||
|
ret = iscsit_send_task_mgt_rsp(cmd, conn);
|
||||||
|
if (ret != 0)
|
||||||
break;
|
break;
|
||||||
case ISTATE_SEND_NOPIN_NO_RESPONSE:
|
ret = iscsit_tmr_post_handler(cmd, conn);
|
||||||
ret = iscsit_send_unsolicited_nopin(cmd,
|
if (ret != 0)
|
||||||
conn, 0);
|
iscsit_fall_back_to_erl0(conn->sess);
|
||||||
if (ret < 0)
|
break;
|
||||||
goto err;
|
case ISTATE_SEND_TEXTRSP:
|
||||||
break;
|
ret = iscsit_send_text_rsp(cmd, conn);
|
||||||
default:
|
break;
|
||||||
pr_err("Unknown Opcode: 0x%02x ITT:"
|
default:
|
||||||
" 0x%08x, i_state: %d on CID: %hu\n",
|
pr_err("Unknown Opcode: 0x%02x ITT:"
|
||||||
cmd->iscsi_opcode, cmd->init_task_tag, state,
|
" 0x%08x, i_state: %d on CID: %hu\n",
|
||||||
conn->cid);
|
cmd->iscsi_opcode, cmd->init_task_tag,
|
||||||
|
state, conn->cid);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (ret < 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (iscsit_send_tx_data(cmd, conn, 1) < 0) {
|
||||||
|
iscsit_tx_thread_wait_for_tcp(conn);
|
||||||
|
iscsit_unmap_iovec(cmd);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
iscsit_unmap_iovec(cmd);
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case ISTATE_SEND_LOGOUTRSP:
|
||||||
|
if (!iscsit_logout_post_handler(cmd, conn))
|
||||||
|
goto restart;
|
||||||
|
/* fall through */
|
||||||
|
case ISTATE_SEND_STATUS:
|
||||||
|
case ISTATE_SEND_ASYNCMSG:
|
||||||
|
case ISTATE_SEND_NOPIN:
|
||||||
|
case ISTATE_SEND_STATUS_RECOVERY:
|
||||||
|
case ISTATE_SEND_TEXTRSP:
|
||||||
|
case ISTATE_SEND_TASKMGTRSP:
|
||||||
|
spin_lock_bh(&cmd->istate_lock);
|
||||||
|
cmd->i_state = ISTATE_SENT_STATUS;
|
||||||
|
spin_unlock_bh(&cmd->istate_lock);
|
||||||
|
break;
|
||||||
|
case ISTATE_SEND_REJECT:
|
||||||
|
if (cmd->cmd_flags & ICF_REJECT_FAIL_CONN) {
|
||||||
|
cmd->cmd_flags &= ~ICF_REJECT_FAIL_CONN;
|
||||||
|
complete(&cmd->reject_comp);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
complete(&cmd->reject_comp);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_err("Unknown Opcode: 0x%02x ITT:"
|
||||||
|
" 0x%08x, i_state: %d on CID: %hu\n",
|
||||||
|
cmd->iscsi_opcode, cmd->init_task_tag,
|
||||||
|
cmd->i_state, conn->cid);
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (atomic_read(&conn->check_immediate_queue))
|
||||||
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
return -1;
|
return -1;
|
||||||
|
restart:
|
||||||
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_response_queue(struct iscsi_conn *conn)
|
static int iscsit_handle_response_queue(struct iscsi_conn *conn)
|
||||||
{
|
{
|
||||||
|
struct iscsit_transport *t = conn->conn_transport;
|
||||||
struct iscsi_queue_req *qr;
|
struct iscsi_queue_req *qr;
|
||||||
struct iscsi_cmd *cmd;
|
struct iscsi_cmd *cmd;
|
||||||
u8 state;
|
u8 state;
|
||||||
|
@ -3695,122 +3861,12 @@ static int handle_response_queue(struct iscsi_conn *conn)
|
||||||
state = qr->state;
|
state = qr->state;
|
||||||
kmem_cache_free(lio_qr_cache, qr);
|
kmem_cache_free(lio_qr_cache, qr);
|
||||||
|
|
||||||
check_rsp_state:
|
ret = t->iscsit_response_queue(conn, cmd, state);
|
||||||
switch (state) {
|
if (ret == 1 || ret < 0)
|
||||||
case ISTATE_SEND_DATAIN:
|
return ret;
|
||||||
ret = iscsit_send_data_in(cmd, conn);
|
|
||||||
if (ret < 0)
|
|
||||||
goto err;
|
|
||||||
else if (!ret)
|
|
||||||
/* more drs */
|
|
||||||
goto check_rsp_state;
|
|
||||||
else if (ret == 1) {
|
|
||||||
/* all done */
|
|
||||||
spin_lock_bh(&cmd->istate_lock);
|
|
||||||
cmd->i_state = ISTATE_SENT_STATUS;
|
|
||||||
spin_unlock_bh(&cmd->istate_lock);
|
|
||||||
|
|
||||||
if (atomic_read(&conn->check_immediate_queue))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
} else if (ret == 2) {
|
|
||||||
/* Still must send status,
|
|
||||||
SCF_TRANSPORT_TASK_SENSE was set */
|
|
||||||
spin_lock_bh(&cmd->istate_lock);
|
|
||||||
cmd->i_state = ISTATE_SEND_STATUS;
|
|
||||||
spin_unlock_bh(&cmd->istate_lock);
|
|
||||||
state = ISTATE_SEND_STATUS;
|
|
||||||
goto check_rsp_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case ISTATE_SEND_STATUS:
|
|
||||||
case ISTATE_SEND_STATUS_RECOVERY:
|
|
||||||
ret = iscsit_send_status(cmd, conn);
|
|
||||||
break;
|
|
||||||
case ISTATE_SEND_LOGOUTRSP:
|
|
||||||
ret = iscsit_send_logout_response(cmd, conn);
|
|
||||||
break;
|
|
||||||
case ISTATE_SEND_ASYNCMSG:
|
|
||||||
ret = iscsit_send_conn_drop_async_message(
|
|
||||||
cmd, conn);
|
|
||||||
break;
|
|
||||||
case ISTATE_SEND_NOPIN:
|
|
||||||
ret = iscsit_send_nopin_response(cmd, conn);
|
|
||||||
break;
|
|
||||||
case ISTATE_SEND_REJECT:
|
|
||||||
ret = iscsit_send_reject(cmd, conn);
|
|
||||||
break;
|
|
||||||
case ISTATE_SEND_TASKMGTRSP:
|
|
||||||
ret = iscsit_send_task_mgt_rsp(cmd, conn);
|
|
||||||
if (ret != 0)
|
|
||||||
break;
|
|
||||||
ret = iscsit_tmr_post_handler(cmd, conn);
|
|
||||||
if (ret != 0)
|
|
||||||
iscsit_fall_back_to_erl0(conn->sess);
|
|
||||||
break;
|
|
||||||
case ISTATE_SEND_TEXTRSP:
|
|
||||||
ret = iscsit_send_text_rsp(cmd, conn);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pr_err("Unknown Opcode: 0x%02x ITT:"
|
|
||||||
" 0x%08x, i_state: %d on CID: %hu\n",
|
|
||||||
cmd->iscsi_opcode, cmd->init_task_tag,
|
|
||||||
state, conn->cid);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (ret < 0)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if (iscsit_send_tx_data(cmd, conn, 1) < 0) {
|
|
||||||
iscsit_tx_thread_wait_for_tcp(conn);
|
|
||||||
iscsit_unmap_iovec(cmd);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
iscsit_unmap_iovec(cmd);
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case ISTATE_SEND_LOGOUTRSP:
|
|
||||||
if (!iscsit_logout_post_handler(cmd, conn))
|
|
||||||
goto restart;
|
|
||||||
/* fall through */
|
|
||||||
case ISTATE_SEND_STATUS:
|
|
||||||
case ISTATE_SEND_ASYNCMSG:
|
|
||||||
case ISTATE_SEND_NOPIN:
|
|
||||||
case ISTATE_SEND_STATUS_RECOVERY:
|
|
||||||
case ISTATE_SEND_TEXTRSP:
|
|
||||||
case ISTATE_SEND_TASKMGTRSP:
|
|
||||||
spin_lock_bh(&cmd->istate_lock);
|
|
||||||
cmd->i_state = ISTATE_SENT_STATUS;
|
|
||||||
spin_unlock_bh(&cmd->istate_lock);
|
|
||||||
break;
|
|
||||||
case ISTATE_SEND_REJECT:
|
|
||||||
if (cmd->cmd_flags & ICF_REJECT_FAIL_CONN) {
|
|
||||||
cmd->cmd_flags &= ~ICF_REJECT_FAIL_CONN;
|
|
||||||
complete(&cmd->reject_comp);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
complete(&cmd->reject_comp);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
pr_err("Unknown Opcode: 0x%02x ITT:"
|
|
||||||
" 0x%08x, i_state: %d on CID: %hu\n",
|
|
||||||
cmd->iscsi_opcode, cmd->init_task_tag,
|
|
||||||
cmd->i_state, conn->cid);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (atomic_read(&conn->check_immediate_queue))
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
|
||||||
return -1;
|
|
||||||
restart:
|
|
||||||
return -EAGAIN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int iscsi_target_tx_thread(void *arg)
|
int iscsi_target_tx_thread(void *arg)
|
||||||
|
@ -3847,11 +3903,11 @@ int iscsi_target_tx_thread(void *arg)
|
||||||
goto transport_err;
|
goto transport_err;
|
||||||
|
|
||||||
get_immediate:
|
get_immediate:
|
||||||
ret = handle_immediate_queue(conn);
|
ret = iscsit_handle_immediate_queue(conn);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto transport_err;
|
goto transport_err;
|
||||||
|
|
||||||
ret = handle_response_queue(conn);
|
ret = iscsit_handle_response_queue(conn);
|
||||||
if (ret == 1)
|
if (ret == 1)
|
||||||
goto get_immediate;
|
goto get_immediate;
|
||||||
else if (ret == -EAGAIN)
|
else if (ret == -EAGAIN)
|
||||||
|
@ -4451,7 +4507,7 @@ static void iscsit_logout_post_handler_diffcid(
|
||||||
/*
|
/*
|
||||||
* Return of 0 causes the TX thread to restart.
|
* Return of 0 causes the TX thread to restart.
|
||||||
*/
|
*/
|
||||||
static int iscsit_logout_post_handler(
|
int iscsit_logout_post_handler(
|
||||||
struct iscsi_cmd *cmd,
|
struct iscsi_cmd *cmd,
|
||||||
struct iscsi_conn *conn)
|
struct iscsi_conn *conn)
|
||||||
{
|
{
|
||||||
|
@ -4509,6 +4565,7 @@ static int iscsit_logout_post_handler(
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(iscsit_logout_post_handler);
|
||||||
|
|
||||||
void iscsit_fail_session(struct iscsi_session *sess)
|
void iscsit_fail_session(struct iscsi_session *sess)
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <target/target_core_fabric_configfs.h>
|
#include <target/target_core_fabric_configfs.h>
|
||||||
#include <target/target_core_configfs.h>
|
#include <target/target_core_configfs.h>
|
||||||
#include <target/configfs_macros.h>
|
#include <target/configfs_macros.h>
|
||||||
|
#include <target/iscsi/iscsi_transport.h>
|
||||||
|
|
||||||
#include "iscsi_target_core.h"
|
#include "iscsi_target_core.h"
|
||||||
#include "iscsi_target_parameters.h"
|
#include "iscsi_target_parameters.h"
|
||||||
|
@ -1536,7 +1537,8 @@ static int lio_queue_data_in(struct se_cmd *se_cmd)
|
||||||
struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
|
struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
|
||||||
|
|
||||||
cmd->i_state = ISTATE_SEND_DATAIN;
|
cmd->i_state = ISTATE_SEND_DATAIN;
|
||||||
iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
|
cmd->conn->conn_transport->iscsit_queue_data_in(cmd->conn, cmd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1568,7 +1570,8 @@ static int lio_queue_status(struct se_cmd *se_cmd)
|
||||||
struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
|
struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
|
||||||
|
|
||||||
cmd->i_state = ISTATE_SEND_STATUS;
|
cmd->i_state = ISTATE_SEND_STATUS;
|
||||||
iscsit_add_cmd_to_response_queue(cmd, cmd->conn, cmd->i_state);
|
cmd->conn->conn_transport->iscsit_queue_status(cmd->conn, cmd);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,8 +60,13 @@ void iscsit_increment_maxcmdsn(struct iscsi_cmd *cmd, struct iscsi_session *sess
|
||||||
|
|
||||||
cmd->maxcmdsn_inc = 1;
|
cmd->maxcmdsn_inc = 1;
|
||||||
|
|
||||||
mutex_lock(&sess->cmdsn_mutex);
|
if (!mutex_trylock(&sess->cmdsn_mutex)) {
|
||||||
|
sess->max_cmd_sn += 1;
|
||||||
|
pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn);
|
||||||
|
return;
|
||||||
|
}
|
||||||
sess->max_cmd_sn += 1;
|
sess->max_cmd_sn += 1;
|
||||||
pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn);
|
pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn);
|
||||||
mutex_unlock(&sess->cmdsn_mutex);
|
mutex_unlock(&sess->cmdsn_mutex);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(iscsit_increment_maxcmdsn);
|
||||||
|
|
|
@ -472,6 +472,7 @@ int iscsit_tmr_post_handler(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(iscsit_tmr_post_handler);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Nothing to do here, but leave it for good measure. :-)
|
* Nothing to do here, but leave it for good measure. :-)
|
||||||
|
|
Loading…
Reference in a new issue