Commit f6cfba1d authored by Mike Christie's avatar Mike Christie Committed by James Bottomley
Browse files

[SCSI] iscsi: data digest calculation fix



From Wang Zhenyu:

data digest fix (the bug caused data corruption w/Wasabi StorageBuilder target)

Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarAlex Aizman <itn780@yahoo.com>
Signed-off-by: default avatarDmitry Yusupov <dmitry_yus@yahoo.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 733bb6a7
Loading
Loading
Loading
Loading
+40 −25
Original line number Diff line number Diff line
@@ -903,11 +903,20 @@ partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg,
	crypto_digest_update(conn->data_rx_tfm, &temp, 1);
}

static void
iscsi_recv_digest_update(struct iscsi_conn *conn, char* buf, int len)
{
	struct scatterlist tmp;

	sg_init_one(&tmp, buf, len);
	crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
}

static int iscsi_scsi_data_in(struct iscsi_conn *conn)
{
	struct iscsi_cmd_task *ctask = conn->in.ctask;
	struct scsi_cmnd *sc = ctask->sc;
	struct scatterlist tmp, *sg;
	struct scatterlist *sg;
	int i, offset, rc = 0;

	BUG_ON((void*)ctask != sc->SCp.ptr);
@@ -921,10 +930,8 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
				      sc->request_bufflen, ctask->data_offset);
		if (rc == -EAGAIN)
			return rc;
		if (conn->datadgst_en) {
			sg_init_one(&tmp, sc->request_buffer, i);
			crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
		}
		if (conn->datadgst_en) 
			iscsi_recv_digest_update(conn, sc->request_buffer, i);
		rc = 0;
		goto done;
	}
@@ -1018,6 +1025,9 @@ iscsi_data_recv(struct iscsi_conn *conn)
		conn->in.hdr = &conn->hdr;
		conn->senselen = (conn->data[0] << 8) | conn->data[1];
		rc = iscsi_cmd_rsp(conn, conn->in.ctask);
		if (!rc && conn->datadgst_en) 
			iscsi_recv_digest_update(conn, conn->data,
						 conn->in.datalen);
	}
	break;
	case ISCSI_OP_TEXT_RSP:
@@ -1042,6 +1052,11 @@ iscsi_data_recv(struct iscsi_conn *conn)
		rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr,
				    conn->data, conn->in.datalen);

		if (!rc && conn->datadgst_en && 
			conn->in.opcode != ISCSI_OP_LOGIN_RSP)
			iscsi_recv_digest_update(conn, conn->data,
			  			conn->in.datalen);

		if (mtask && conn->login_mtask != mtask) {
			spin_lock(&session->lock);
			__kfifo_put(session->mgmtpool.queue, (void*)&mtask,
@@ -1050,6 +1065,8 @@ iscsi_data_recv(struct iscsi_conn *conn)
		}
	}
	break;
	case ISCSI_OP_ASYNC_EVENT:
	case ISCSI_OP_REJECT:
	default:
		BUG_ON(1);
	}
@@ -1112,7 +1129,7 @@ more:
		rc = iscsi_hdr_recv(conn);
		if (!rc && conn->in.datalen) {
			if (conn->datadgst_en &&
			    conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
				conn->in.opcode != ISCSI_OP_LOGIN_RSP) {
				BUG_ON(!conn->data_rx_tfm);
				crypto_digest_init(conn->data_rx_tfm);
			}
@@ -1124,10 +1141,9 @@ more:
	}

	if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
		uint32_t recv_digest;
		debug_tcp("extra data_recv offset %d copy %d\n",
			  conn->in.offset, conn->in.copy);
		if (conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
			uint32_t recv_digest;
		skb_copy_bits(conn->in.skb, conn->in.offset,
				&recv_digest, 4);
		conn->in.offset += 4;
@@ -1145,7 +1161,6 @@ more:
			conn->in_progress = IN_PROGRESS_WAIT_HEADER;
		}
	}
	}

	if (conn->in_progress == IN_PROGRESS_DATA_RECV && conn->in.copy) {

@@ -1165,7 +1180,7 @@ more:
		conn->in.copy -= conn->in.padding;
		conn->in.offset += conn->in.padding;
		if (conn->datadgst_en &&
		    conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
			conn->in.opcode != ISCSI_OP_LOGIN_RSP) {
			if (conn->in.padding) {
				debug_tcp("padding -> %d\n", conn->in.padding);
				memset(pad, 0, conn->in.padding);