in iscsi/iscsi_target_seq_pdu_list.c [285:484]
static int iscsit_do_build_pdu_and_seq_lists(
struct iscsi_cmd *cmd,
struct iscsi_build_list *bl)
{
int check_immediate = 0, datapduinorder, datasequenceinorder;
u32 burstlength = 0, offset = 0, i = 0, mdsl;
u32 pdu_count = 0, seq_no = 0, unsolicited_data_length = 0;
struct iscsi_conn *conn = cmd->conn;
struct iscsi_pdu *pdu = cmd->pdu_list;
struct iscsi_seq *seq = cmd->seq_list;
if (cmd->se_cmd.data_direction == DMA_TO_DEVICE)
mdsl = cmd->conn->conn_ops->MaxXmitDataSegmentLength;
else
mdsl = cmd->conn->conn_ops->MaxRecvDataSegmentLength;
datapduinorder = conn->sess->sess_ops->DataPDUInOrder;
datasequenceinorder = conn->sess->sess_ops->DataSequenceInOrder;
if ((bl->type == PDULIST_IMMEDIATE) ||
(bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
check_immediate = 1;
if ((bl->type == PDULIST_UNSOLICITED) ||
(bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
unsolicited_data_length = min(cmd->se_cmd.data_length,
conn->sess->sess_ops->FirstBurstLength);
while (offset < cmd->se_cmd.data_length) {
pdu_count++;
if (!datapduinorder) {
pdu[i].offset = offset;
pdu[i].seq_no = seq_no;
}
if (!datasequenceinorder && (pdu_count == 1)) {
seq[seq_no].pdu_start = i;
seq[seq_no].seq_no = seq_no;
seq[seq_no].offset = offset;
seq[seq_no].orig_offset = offset;
}
if (check_immediate) {
check_immediate = 0;
if (!datapduinorder) {
pdu[i].type = PDUTYPE_IMMEDIATE;
pdu[i++].length = bl->immediate_data_length;
}
if (!datasequenceinorder) {
seq[seq_no].type = SEQTYPE_IMMEDIATE;
seq[seq_no].pdu_count = 1;
seq[seq_no].xfer_len =
bl->immediate_data_length;
}
offset += bl->immediate_data_length;
pdu_count = 0;
seq_no++;
if (unsolicited_data_length)
unsolicited_data_length -=
bl->immediate_data_length;
continue;
}
if (unsolicited_data_length > 0) {
if ((offset + mdsl) >= cmd->se_cmd.data_length) {
if (!datapduinorder) {
pdu[i].type = PDUTYPE_UNSOLICITED;
pdu[i].length =
(cmd->se_cmd.data_length - offset);
}
if (!datasequenceinorder) {
seq[seq_no].type = SEQTYPE_UNSOLICITED;
seq[seq_no].pdu_count = pdu_count;
seq[seq_no].xfer_len = (burstlength +
(cmd->se_cmd.data_length - offset));
}
unsolicited_data_length -=
(cmd->se_cmd.data_length - offset);
offset += (cmd->se_cmd.data_length - offset);
continue;
}
if ((offset + mdsl) >=
conn->sess->sess_ops->FirstBurstLength) {
if (!datapduinorder) {
pdu[i].type = PDUTYPE_UNSOLICITED;
pdu[i++].length =
(conn->sess->sess_ops->FirstBurstLength -
offset);
}
if (!datasequenceinorder) {
seq[seq_no].type = SEQTYPE_UNSOLICITED;
seq[seq_no].pdu_count = pdu_count;
seq[seq_no].xfer_len = (burstlength +
(conn->sess->sess_ops->FirstBurstLength -
offset));
}
unsolicited_data_length -=
(conn->sess->sess_ops->FirstBurstLength -
offset);
offset += (conn->sess->sess_ops->FirstBurstLength -
offset);
burstlength = 0;
pdu_count = 0;
seq_no++;
continue;
}
if (!datapduinorder) {
pdu[i].type = PDUTYPE_UNSOLICITED;
pdu[i++].length = mdsl;
}
burstlength += mdsl;
offset += mdsl;
unsolicited_data_length -= mdsl;
continue;
}
if ((offset + mdsl) >= cmd->se_cmd.data_length) {
if (!datapduinorder) {
pdu[i].type = PDUTYPE_NORMAL;
pdu[i].length = (cmd->se_cmd.data_length - offset);
}
if (!datasequenceinorder) {
seq[seq_no].type = SEQTYPE_NORMAL;
seq[seq_no].pdu_count = pdu_count;
seq[seq_no].xfer_len = (burstlength +
(cmd->se_cmd.data_length - offset));
}
offset += (cmd->se_cmd.data_length - offset);
continue;
}
if ((burstlength + mdsl) >=
conn->sess->sess_ops->MaxBurstLength) {
if (!datapduinorder) {
pdu[i].type = PDUTYPE_NORMAL;
pdu[i++].length =
(conn->sess->sess_ops->MaxBurstLength -
burstlength);
}
if (!datasequenceinorder) {
seq[seq_no].type = SEQTYPE_NORMAL;
seq[seq_no].pdu_count = pdu_count;
seq[seq_no].xfer_len = (burstlength +
(conn->sess->sess_ops->MaxBurstLength -
burstlength));
}
offset += (conn->sess->sess_ops->MaxBurstLength -
burstlength);
burstlength = 0;
pdu_count = 0;
seq_no++;
continue;
}
if (!datapduinorder) {
pdu[i].type = PDUTYPE_NORMAL;
pdu[i++].length = mdsl;
}
burstlength += mdsl;
offset += mdsl;
}
if (!datasequenceinorder) {
if (bl->data_direction & ISCSI_PDU_WRITE) {
if (bl->randomize & RANDOM_R2T_OFFSETS) {
if (iscsit_randomize_seq_lists(cmd, bl->type)
< 0)
return -1;
} else
iscsit_ordered_seq_lists(cmd, bl->type);
} else if (bl->data_direction & ISCSI_PDU_READ) {
if (bl->randomize & RANDOM_DATAIN_SEQ_OFFSETS) {
if (iscsit_randomize_seq_lists(cmd, bl->type)
< 0)
return -1;
} else
iscsit_ordered_seq_lists(cmd, bl->type);
}
iscsit_dump_seq_list(cmd);
}
if (!datapduinorder) {
if (bl->data_direction & ISCSI_PDU_WRITE) {
if (bl->randomize & RANDOM_DATAOUT_PDU_OFFSETS) {
if (iscsit_randomize_pdu_lists(cmd, bl->type)
< 0)
return -1;
} else
iscsit_ordered_pdu_lists(cmd, bl->type);
} else if (bl->data_direction & ISCSI_PDU_READ) {
if (bl->randomize & RANDOM_DATAIN_PDU_OFFSETS) {
if (iscsit_randomize_pdu_lists(cmd, bl->type)
< 0)
return -1;
} else
iscsit_ordered_pdu_lists(cmd, bl->type);
}
iscsit_dump_pdu_list(cmd);
}
return 0;
}