lib/iscsi: Send R2T in SCSI Data-Out PDU Header handling
Recent patches refactored iSCSI target to separate PDU header
and payload handling. However for SCSI Data-Out PDU, the division
of roles done by refactoring was wrong. Before refactoring, LUN
hotplug was checked after sending R2T, but after refactoring LUN
hotplug is checked before sending R2T. This change stopped PDU
exchange between iSCSI initiator and target and caused timeout of
LUN removal.
This patch restores the original ordering of checking LUN hotplug
and sending R2T by changing the division of roles.
SCSI Write Command PDU handling don't have any issue related with
this.
Fixes #1004
Signed-off-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/472308 (master)
(cherry picked from commit 84f59335c2
)
Change-Id: I7b2866d8394b522fb5420d2936de2fbddc7d1daa
Signed-off-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/472775
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
This commit is contained in:
parent
4130dd8ea5
commit
6012461966
@ -4385,8 +4385,11 @@ iscsi_pdu_hdr_op_data(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
|
|||||||
struct spdk_scsi_lun *lun_dev;
|
struct spdk_scsi_lun *lun_dev;
|
||||||
uint32_t transfer_tag;
|
uint32_t transfer_tag;
|
||||||
uint32_t task_tag;
|
uint32_t task_tag;
|
||||||
|
uint32_t transfer_len;
|
||||||
uint32_t DataSN;
|
uint32_t DataSN;
|
||||||
uint32_t buffer_offset;
|
uint32_t buffer_offset;
|
||||||
|
uint32_t len;
|
||||||
|
int F_bit;
|
||||||
int rc;
|
int rc;
|
||||||
int reject_reason = ISCSI_REASON_INVALID_PDU_FIELD;
|
int reject_reason = ISCSI_REASON_INVALID_PDU_FIELD;
|
||||||
|
|
||||||
@ -4396,6 +4399,7 @@ iscsi_pdu_hdr_op_data(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
reqh = (struct iscsi_bhs_data_out *)&pdu->bhs;
|
reqh = (struct iscsi_bhs_data_out *)&pdu->bhs;
|
||||||
|
F_bit = !!(reqh->flags & ISCSI_FLAG_FINAL);
|
||||||
transfer_tag = from_be32(&reqh->ttt);
|
transfer_tag = from_be32(&reqh->ttt);
|
||||||
task_tag = from_be32(&reqh->itt);
|
task_tag = from_be32(&reqh->itt);
|
||||||
DataSN = from_be32(&reqh->data_sn);
|
DataSN = from_be32(&reqh->data_sn);
|
||||||
@ -4440,13 +4444,26 @@ iscsi_pdu_hdr_op_data(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
|
|||||||
return SPDK_ISCSI_CONNECTION_FATAL;
|
return SPDK_ISCSI_CONNECTION_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task->current_r2t_length + pdu->data_segment_len > conn->sess->MaxBurstLength) {
|
transfer_len = task->scsi.transfer_len;
|
||||||
SPDK_ERRLOG("R2T burst(%zu) > MaxBurstLength(%u)\n",
|
task->current_r2t_length += pdu->data_segment_len;
|
||||||
task->current_r2t_length + pdu->data_segment_len,
|
task->next_expected_r2t_offset += pdu->data_segment_len;
|
||||||
|
task->r2t_datasn++;
|
||||||
|
|
||||||
|
if (task->current_r2t_length > conn->sess->MaxBurstLength) {
|
||||||
|
SPDK_ERRLOG("R2T burst(%u) > MaxBurstLength(%u)\n",
|
||||||
|
task->current_r2t_length,
|
||||||
conn->sess->MaxBurstLength);
|
conn->sess->MaxBurstLength);
|
||||||
return SPDK_ISCSI_CONNECTION_FATAL;
|
return SPDK_ISCSI_CONNECTION_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (F_bit) {
|
||||||
|
/*
|
||||||
|
* This R2T burst is done. Clear the length before we
|
||||||
|
* receive a PDU for the next R2t burst.
|
||||||
|
*/
|
||||||
|
task->current_r2t_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
subtask = spdk_iscsi_task_get(conn, task, spdk_iscsi_task_cpl);
|
subtask = spdk_iscsi_task_get(conn, task, spdk_iscsi_task_cpl);
|
||||||
if (subtask == NULL) {
|
if (subtask == NULL) {
|
||||||
SPDK_ERRLOG("Unable to acquire subtask\n");
|
SPDK_ERRLOG("Unable to acquire subtask\n");
|
||||||
@ -4456,6 +4473,20 @@ iscsi_pdu_hdr_op_data(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
|
|||||||
subtask->scsi.length = pdu->data_segment_len;
|
subtask->scsi.length = pdu->data_segment_len;
|
||||||
spdk_iscsi_task_associate_pdu(subtask, pdu);
|
spdk_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)) {
|
||||||
|
task->acked_r2tsn++;
|
||||||
|
len = DMIN32(conn->sess->MaxBurstLength, (transfer_len -
|
||||||
|
task->next_r2t_offset));
|
||||||
|
rc = iscsi_send_r2t(conn, task, task->next_r2t_offset, len,
|
||||||
|
task->ttt, &task->R2TSN);
|
||||||
|
if (rc < 0) {
|
||||||
|
SPDK_ERRLOG("iscsi_send_r2t() failed\n");
|
||||||
|
}
|
||||||
|
task->next_r2t_offset += len;
|
||||||
|
}
|
||||||
|
|
||||||
if (lun_dev == NULL) {
|
if (lun_dev == NULL) {
|
||||||
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "LUN %d is removed, complete the task immediately\n",
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "LUN %d is removed, complete the task immediately\n",
|
||||||
task->lun_id);
|
task->lun_id);
|
||||||
@ -4481,36 +4512,13 @@ reject_return:
|
|||||||
static int
|
static int
|
||||||
iscsi_pdu_payload_op_data(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
|
iscsi_pdu_payload_op_data(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu)
|
||||||
{
|
{
|
||||||
struct spdk_iscsi_task *task, *subtask;
|
struct spdk_iscsi_task *subtask;
|
||||||
struct iscsi_bhs_data_out *reqh;
|
|
||||||
uint32_t transfer_len;
|
|
||||||
uint32_t len;
|
|
||||||
int F_bit;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (pdu->task == NULL) {
|
if (pdu->task == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
subtask = pdu->task;
|
subtask = pdu->task;
|
||||||
task = spdk_iscsi_task_get_primary(subtask);
|
|
||||||
assert(task != subtask);
|
|
||||||
|
|
||||||
reqh = (struct iscsi_bhs_data_out *)&pdu->bhs;
|
|
||||||
F_bit = !!(reqh->flags & ISCSI_FLAG_FINAL);
|
|
||||||
|
|
||||||
transfer_len = task->scsi.transfer_len;
|
|
||||||
task->current_r2t_length += pdu->data_segment_len;
|
|
||||||
task->next_expected_r2t_offset += pdu->data_segment_len;
|
|
||||||
task->r2t_datasn++;
|
|
||||||
|
|
||||||
if (F_bit) {
|
|
||||||
/*
|
|
||||||
* This R2T burst is done. Clear the length before we
|
|
||||||
* receive a PDU for the next R2T burst.
|
|
||||||
*/
|
|
||||||
task->current_r2t_length = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spdk_likely(!pdu->dif_insert_or_strip)) {
|
if (spdk_likely(!pdu->dif_insert_or_strip)) {
|
||||||
spdk_scsi_task_set_data(&subtask->scsi, pdu->data, pdu->data_segment_len);
|
spdk_scsi_task_set_data(&subtask->scsi, pdu->data, pdu->data_segment_len);
|
||||||
@ -4518,23 +4526,9 @@ iscsi_pdu_payload_op_data(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *p
|
|||||||
spdk_scsi_task_set_data(&subtask->scsi, pdu->data, pdu->data_buf_len);
|
spdk_scsi_task_set_data(&subtask->scsi, pdu->data, pdu->data_buf_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task->next_expected_r2t_offset == transfer_len) {
|
if (spdk_scsi_dev_get_lun(conn->dev, subtask->lun_id) == NULL) {
|
||||||
task->acked_r2tsn++;
|
|
||||||
} else if (F_bit && (task->next_r2t_offset < transfer_len)) {
|
|
||||||
task->acked_r2tsn++;
|
|
||||||
len = DMIN32(conn->sess->MaxBurstLength, (transfer_len -
|
|
||||||
task->next_r2t_offset));
|
|
||||||
rc = iscsi_send_r2t(conn, task, task->next_r2t_offset, len,
|
|
||||||
task->ttt, &task->R2TSN);
|
|
||||||
if (rc < 0) {
|
|
||||||
SPDK_ERRLOG("iscsi_send_r2t() failed\n");
|
|
||||||
}
|
|
||||||
task->next_r2t_offset += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spdk_scsi_dev_get_lun(conn->dev, task->lun_id) == NULL) {
|
|
||||||
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "LUN %d is removed, complete the task immediately\n",
|
SPDK_DEBUGLOG(SPDK_LOG_ISCSI, "LUN %d is removed, complete the task immediately\n",
|
||||||
task->lun_id);
|
subtask->lun_id);
|
||||||
subtask->scsi.transfer_len = subtask->scsi.length;
|
subtask->scsi.transfer_len = subtask->scsi.length;
|
||||||
spdk_scsi_task_process_null_lun(&subtask->scsi);
|
spdk_scsi_task_process_null_lun(&subtask->scsi);
|
||||||
spdk_iscsi_task_cpl(&subtask->scsi);
|
spdk_iscsi_task_cpl(&subtask->scsi);
|
||||||
|
Loading…
Reference in New Issue
Block a user