static int iscsit_do_build_pdu_and_seq_lists()

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;
}