lib/iscsi: Create subtask after reading data segment for Data-OUT PDU
The following patches will change the handler for Data-OUT PDU to submit subtask only when 64KB data is read or F bit is set. Previously, we had created a subtask when processing header and before reading data segment. Creating a subtask beforehand is not convenient for the following changes. Hence create a subtask after reading data segment. If LUN is removed while processing the Data-OUT PDU, the corresponding primary task will be terminated by iscsi_clear_all_transfer_task(), and any subtask completion is not sent to initiator. Hence we can reject the received Data-OUT PDU safely. Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Change-Id: Ifb6d6988676080b458b31d12fef065f3c1de0cb6 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6415 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Mellanox Build Bot Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
This commit is contained in:
parent
59237d22b8
commit
2ef97692bc
@ -4142,7 +4142,7 @@ iscsi_pdu_hdr_op_snack(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
|
||||
static int
|
||||
iscsi_pdu_hdr_op_data(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
|
||||
{
|
||||
struct spdk_iscsi_task *task, *subtask;
|
||||
struct spdk_iscsi_task *task;
|
||||
struct iscsi_bhs_data_out *reqh;
|
||||
struct spdk_scsi_lun *lun_dev;
|
||||
uint32_t transfer_tag;
|
||||
@ -4225,15 +4225,6 @@ iscsi_pdu_hdr_op_data(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
|
||||
task->current_r2t_length = 0;
|
||||
}
|
||||
|
||||
subtask = iscsi_task_get(conn, task, iscsi_task_cpl);
|
||||
if (subtask == NULL) {
|
||||
SPDK_ERRLOG("Unable to acquire subtask\n");
|
||||
return SPDK_ISCSI_CONNECTION_FATAL;
|
||||
}
|
||||
subtask->scsi.offset = buffer_offset;
|
||||
subtask->scsi.length = pdu->data_segment_len;
|
||||
iscsi_task_associate_pdu(subtask, pdu);
|
||||
|
||||
if (task->next_expected_r2t_offset == transfer_len) {
|
||||
task->acked_r2tsn++;
|
||||
} else if (F_bit && (task->next_r2t_offset < transfer_len)) {
|
||||
@ -4249,61 +4240,55 @@ iscsi_pdu_hdr_op_data(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
|
||||
}
|
||||
|
||||
if (lun_dev == NULL) {
|
||||
SPDK_DEBUGLOG(iscsi, "LUN %d is removed, complete the task immediately\n",
|
||||
SPDK_DEBUGLOG(iscsi, "LUN %d is removed, reject this PDU.\n",
|
||||
task->lun_id);
|
||||
subtask->scsi.transfer_len = subtask->scsi.length;
|
||||
spdk_scsi_task_process_null_lun(&subtask->scsi);
|
||||
iscsi_task_cpl(&subtask->scsi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (spdk_unlikely(spdk_scsi_lun_get_dif_ctx(lun_dev, &subtask->scsi, &pdu->dif_ctx))) {
|
||||
return iscsi_reject(conn, pdu, ISCSI_REASON_PROTOCOL_ERROR);
|
||||
} else if (spdk_unlikely(spdk_scsi_lun_get_dif_ctx(lun_dev, &task->scsi, &pdu->dif_ctx))) {
|
||||
pdu->dif_insert_or_strip = true;
|
||||
}
|
||||
|
||||
pdu->task = subtask;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
iscsi_pdu_payload_op_data(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
|
||||
{
|
||||
struct spdk_iscsi_task *subtask;
|
||||
struct spdk_iscsi_task *task, *subtask;
|
||||
struct iscsi_bhs_data_out *reqh;
|
||||
uint32_t transfer_tag;
|
||||
|
||||
if (pdu->task == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
subtask = pdu->task;
|
||||
uint32_t buffer_offset;
|
||||
|
||||
reqh = (struct iscsi_bhs_data_out *)&pdu->bhs;
|
||||
transfer_tag = from_be32(&reqh->ttt);
|
||||
buffer_offset = from_be32(&reqh->buffer_offset);
|
||||
|
||||
if (get_transfer_task(conn, transfer_tag) == NULL) {
|
||||
task = get_transfer_task(conn, transfer_tag);
|
||||
if (spdk_unlikely(task == NULL)) {
|
||||
SPDK_ERRLOG("Not found for transfer_tag=%x\n", transfer_tag);
|
||||
subtask->scsi.transfer_len = subtask->scsi.length;
|
||||
spdk_scsi_task_process_abort(&subtask->scsi);
|
||||
iscsi_task_cpl(&subtask->scsi);
|
||||
return 0;
|
||||
return iscsi_reject(conn, pdu, ISCSI_REASON_INVALID_PDU_FIELD);
|
||||
}
|
||||
|
||||
if (spdk_scsi_dev_get_lun(conn->dev, task->lun_id) == NULL) {
|
||||
SPDK_DEBUGLOG(iscsi, "LUN %d is removed, reject this PDU.\n",
|
||||
task->lun_id);
|
||||
return iscsi_reject(conn, pdu, ISCSI_REASON_PROTOCOL_ERROR);
|
||||
}
|
||||
|
||||
subtask = iscsi_task_get(conn, task, iscsi_task_cpl);
|
||||
if (subtask == NULL) {
|
||||
SPDK_ERRLOG("Unable to acquire subtask\n");
|
||||
return SPDK_ISCSI_CONNECTION_FATAL;
|
||||
}
|
||||
subtask->scsi.offset = buffer_offset;
|
||||
subtask->scsi.length = pdu->data_segment_len;
|
||||
iscsi_task_associate_pdu(subtask, pdu);
|
||||
|
||||
if (spdk_likely(!pdu->dif_insert_or_strip)) {
|
||||
spdk_scsi_task_set_data(&subtask->scsi, pdu->data, pdu->data_segment_len);
|
||||
} else {
|
||||
spdk_scsi_task_set_data(&subtask->scsi, pdu->data, pdu->data_buf_len);
|
||||
}
|
||||
|
||||
if (spdk_scsi_dev_get_lun(conn->dev, subtask->lun_id) == NULL) {
|
||||
SPDK_DEBUGLOG(iscsi, "LUN %d is removed, complete the task immediately\n",
|
||||
subtask->lun_id);
|
||||
subtask->scsi.transfer_len = subtask->scsi.length;
|
||||
spdk_scsi_task_process_null_lun(&subtask->scsi);
|
||||
iscsi_task_cpl(&subtask->scsi);
|
||||
return 0;
|
||||
}
|
||||
|
||||
iscsi_queue_task(conn, subtask);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1858,7 +1858,7 @@ check_iscsi_r2t(struct spdk_iscsi_task *task, uint32_t len)
|
||||
rsph = (struct iscsi_bhs_r2t *)&rsp_pdu->bhs;
|
||||
CU_ASSERT(rsph->opcode == ISCSI_OP_R2T);
|
||||
CU_ASSERT(from_be64(&rsph->lun) == spdk_scsi_lun_id_int_to_fmt(task->lun_id));
|
||||
CU_ASSERT(from_be32(&rsph->buffer_offset) == task->next_r2t_offset);
|
||||
CU_ASSERT(from_be32(&rsph->buffer_offset) + len == task->next_r2t_offset);
|
||||
CU_ASSERT(from_be32(&rsph->desired_xfer_len) == len);
|
||||
|
||||
TAILQ_REMOVE(&g_write_pdu_list, rsp_pdu, tailq);
|
||||
@ -1955,10 +1955,10 @@ pdu_hdr_op_data_test(void)
|
||||
|
||||
rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(pdu.task == NULL);
|
||||
check_iscsi_reject(&pdu, ISCSI_REASON_PROTOCOL_ERROR);
|
||||
|
||||
/* Case 10 - SCSI Data-Out PDU is correct and processed. Created task is held
|
||||
* to the PDU, but its F bit is 0 and hence R2T is not sent.
|
||||
/* Case 10 - SCSI Data-Out PDU is correct and processed. Its F bit is 0 and hence
|
||||
* R2T is not sent.
|
||||
*/
|
||||
dev.lun[0] = &lun;
|
||||
to_be32(&data_reqh->data_sn, primary.r2t_datasn);
|
||||
@ -1966,12 +1966,11 @@ pdu_hdr_op_data_test(void)
|
||||
|
||||
rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(pdu.task != NULL);
|
||||
iscsi_task_put(pdu.task);
|
||||
CU_ASSERT(!pdu.is_rejected);
|
||||
pdu.task = NULL;
|
||||
|
||||
/* Case 11 - SCSI Data-Out PDU is correct and processed. Created task is held
|
||||
* to the PDU, and Its F bit is 1 and hence R2T is sent.
|
||||
/* Case 11 - SCSI Data-Out PDU is correct and processed. Its F bit is 1 and hence
|
||||
* R2T is sent.
|
||||
*/
|
||||
data_reqh->flags |= ISCSI_FLAG_FINAL;
|
||||
to_be32(&data_reqh->data_sn, primary.r2t_datasn);
|
||||
@ -1980,19 +1979,8 @@ pdu_hdr_op_data_test(void)
|
||||
|
||||
rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(pdu.task != NULL);
|
||||
check_iscsi_r2t(pdu.task, pdu.data_segment_len * 4);
|
||||
iscsi_task_put(pdu.task);
|
||||
|
||||
/* Case 12 - Task pool is empty. */
|
||||
to_be32(&data_reqh->data_sn, primary.r2t_datasn);
|
||||
to_be32(&data_reqh->buffer_offset, primary.next_expected_r2t_offset);
|
||||
g_task_pool_is_empty = true;
|
||||
|
||||
rc = iscsi_pdu_hdr_op_data(&conn, &pdu);
|
||||
CU_ASSERT(rc == SPDK_ISCSI_CONNECTION_FATAL);
|
||||
|
||||
g_task_pool_is_empty = false;
|
||||
CU_ASSERT(!pdu.is_rejected);
|
||||
check_iscsi_r2t(&primary, pdu.data_segment_len * 4);
|
||||
}
|
||||
|
||||
/* Test an ISCSI_OP_TEXT PDU with CONTINUE bit set but
|
||||
|
Loading…
Reference in New Issue
Block a user