[Stgt-devel] [PATCH 03/20] iser transport buf

Pete Wyckoff pw
Tue Oct 16 17:18:57 CEST 2007


For RDMA, it is often nice to use data from a pool of pre-registered
buffers.  To do this, the transport allocates memory for a response and
passes it down to the devices to fill.  Some operations, though,
allocate their own buffers and return that new memory instead.  These
are usually small and the allocation is just done for convenience to
avoid length bounds checking.  Copy the data into the provided transport
buffer instead.

If the transport does not provide a buffer at cmd->uaddr, the newly
alloced buffer is returned as before.

Also fixes some leaks of these extra buffers in error paths, and cleans
up unreachable code in ibmvio inquiry.

Signed-off-by: Pete Wyckoff <pw at osc.edu>
---
 usr/ibmvio/ibmvio.c |   25 +++++++++----------------
 usr/mmc.c           |    6 ++----
 usr/sbc.c           |    3 +--
 usr/smc.c           |    9 +++++----
 usr/spc.c           |   36 +++++++++++++++++++++++++++---------
 usr/spc.h           |    1 +
 6 files changed, 45 insertions(+), 35 deletions(-)

diff --git a/usr/ibmvio/ibmvio.c b/usr/ibmvio/ibmvio.c
index cdd3782..a0002cf 100644
--- a/usr/ibmvio/ibmvio.c
+++ b/usr/ibmvio/ibmvio.c
@@ -143,10 +143,16 @@ static int ibmvio_inquiry(int host_no, struct scsi_cmd *cmd)
 	uint8_t *data, *scb = cmd->scb;
 	unsigned char key = ILLEGAL_REQUEST;
 	uint16_t asc = ASC_INVALID_FIELD_IN_CDB;
+	uint32_t len;
 
 	if (((scb[1] & 0x3) == 0x3) || (!(scb[1] & 0x3) && scb[2]))
 		goto sense;
 
+	dprintf("%x %x\n", scb[1], scb[2]);
+
+	if (scb[1] & 0x3)
+		return spc_inquiry(host_no, cmd);
+
 	data = valloc(pagesize);
 	if (!data) {
 		key = HARDWARE_ERROR;
@@ -155,23 +161,12 @@ static int ibmvio_inquiry(int host_no, struct scsi_cmd *cmd)
 	}
 	memset(data, 0, pagesize);
 
-	dprintf("%x %x\n", scb[1], scb[2]);
-
-	if (!(scb[1] & 0x3)) {
-		cmd->len = __ibmvio_inquiry(host_no, cmd, data);
-		ret = SAM_STAT_GOOD;
-	} else
-		return spc_inquiry(host_no, cmd);
-
-	if (ret != SAM_STAT_GOOD)
-		goto sense;
-
-	cmd->len = min_t(int, cmd->len, scb[4]);
-	cmd->uaddr = (unsigned long) data;
+	len = __ibmvio_inquiry(host_no, cmd, data);
 
 	if (cmd->dev->lun != cmd->dev_id)
 		data[0] = TYPE_NO_LUN;
 
+	spc_return_buf(cmd, data, min_t(int, len, scb[4]));
 	return SAM_STAT_GOOD;
 sense:
 	cmd->len = 0;
@@ -194,7 +189,6 @@ static int ibmvio_report_luns(int host_no, struct scsi_cmd *cmd)
 	struct list_head *dev_list = &cmd->c_target->device_list;
 	uint64_t lun, *data;
 	int idx, alen, oalen, nr_luns, rbuflen = 4096;
-	int *len = &cmd->len;
 	uint8_t *lun_buf = cmd->lun;
 	unsigned char key = ILLEGAL_REQUEST;
 	uint16_t asc = ASC_INVALID_FIELD_IN_CDB;
@@ -210,7 +204,6 @@ static int ibmvio_report_luns(int host_no, struct scsi_cmd *cmd)
 		goto sense;
 	}
 	memset(data, 0, pagesize);
-	cmd->uaddr = (unsigned long)data;
 
 	alen &= ~(8 - 1);
 	oalen = alen;
@@ -240,7 +233,7 @@ static int ibmvio_report_luns(int host_no, struct scsi_cmd *cmd)
 
 done:
 	*((uint32_t *) data) = __cpu_to_be32(nr_luns * 8);
-	*len = min(oalen, nr_luns * 8 + 8);
+	spc_return_buf(cmd, data, min(oalen, nr_luns * 8 + 8));
 	return SAM_STAT_GOOD;
 sense:
 	*len = 0;
diff --git a/usr/mmc.c b/usr/mmc.c
index 0a0c033..b0b5d41 100644
--- a/usr/mmc.c
+++ b/usr/mmc.c
@@ -75,7 +75,6 @@ static int mmc_read_toc(int host_no, struct scsi_cmd *cmd)
 		return SAM_STAT_CHECK_CONDITION;
 	}
 	memset(data, 0, pagesize);
-	cmd->uaddr = (unsigned long) data;
 
 	/* forged for single session data cd only. all iso file fall into this */
 	if (cmd->scb[1] & 0x2) {
@@ -94,7 +93,7 @@ static int mmc_read_toc(int host_no, struct scsi_cmd *cmd)
 		data[6] = 0x01;
 	}
 
-	cmd->len = data[1] + 2;
+	spc_return_buf(cmd, data, data[1] + 2);
 
 	return SAM_STAT_GOOD;
 }
@@ -111,14 +110,13 @@ static int mmc_read_capacity(int host_no, struct scsi_cmd *cmd)
 		return SAM_STAT_CHECK_CONDITION;
 	}
 	memset(data, 0, pagesize);
-	cmd->uaddr = (unsigned long) data;
 
 	size = cmd->dev->size >> MMC_BLK_SHIFT;
 
 	data[0] = (size >> 32) ?
 		__cpu_to_be32(0xffffffff) : __cpu_to_be32(size - 1);
 	data[1] = __cpu_to_be32(1U << MMC_BLK_SHIFT);
-	cmd->len = 8;
+	spc_return_buf(cmd, data, 8);
 
 	return SAM_STAT_GOOD;
 }
diff --git a/usr/sbc.c b/usr/sbc.c
index d862e6b..1a47a24 100644
--- a/usr/sbc.c
+++ b/usr/sbc.c
@@ -121,15 +121,14 @@ static int sbc_read_capacity(int host_no, struct scsi_cmd *cmd)
 		asc = ASC_INTERNAL_TGT_FAILURE;
 		goto sense;
 	}
-	cmd->uaddr = (unsigned long) data;
 
 	size = cmd->dev->size >> BLK_SHIFT;
 
 	data[0] = (size >> 32) ?
 		__cpu_to_be32(0xffffffff) : __cpu_to_be32(size - 1);
 	data[1] = __cpu_to_be32(1U << BLK_SHIFT);
-	cmd->len = 8;
 
+	spc_return_buf(cmd, data, 8);
 	return SAM_STAT_GOOD;
 sense:
 	cmd->len = 0;
diff --git a/usr/smc.c b/usr/smc.c
index df38b25..7b99a42 100644
--- a/usr/smc.c
+++ b/usr/smc.c
@@ -282,8 +282,10 @@ static int smc_read_element_status(int host_no, struct scsi_cmd *cmd)
 	}
 	memset(data, 0, pagesize);
 
-	if (scb[11])	/* Reserved byte */
+	if (scb[11]) {	/* Reserved byte */
+		free(data);
 		goto sense;
+	}
 
 	switch(element_type) {
 	case ELEMENT_ANY:
@@ -333,6 +335,7 @@ static int smc_read_element_status(int host_no, struct scsi_cmd *cmd)
 						  dvcid, voltag);
 		break;
 	default:
+		free(data);
 		goto sense;
 		break;
 	}
@@ -340,10 +343,8 @@ static int smc_read_element_status(int host_no, struct scsi_cmd *cmd)
 	/* Lastly, fill in data header */
 	len = element_status_data_hdr(data, dvcid, voltag, first, count);
 
-	cmd->len = min_t(int, len, alloc_len);
-	cmd->uaddr = (unsigned long) data;
 	cmd->rw = READ;
-
+	spc_return_buf(cmd, data, min_t(int, len, alloc_len));
 	return SAM_STAT_GOOD;
 
 sense:
diff --git a/usr/spc.c b/usr/spc.c
index 45a0430..1d7625d 100644
--- a/usr/spc.c
+++ b/usr/spc.c
@@ -140,6 +140,22 @@ void update_vpd_83(struct scsi_lu *lu, void *id)
 	strncpy((char *)data + 4, id, SCSI_ID_LEN);
 }
 
+/*
+ * Helper to move return data into read result buffer allocated by transport,
+ * if one exists.
+ */
+void spc_return_buf(struct scsi_cmd *cmd, void *data, uint32_t len)
+{
+	if (cmd->uaddr) {
+		memcpy((void *) (unsigned long) cmd->uaddr, data,
+		       min(cmd->len, len));
+		free(data);
+	} else {
+		cmd->uaddr = (unsigned long) data;
+	}
+	cmd->len = len;
+}
+
 int spc_inquiry(int host_no, struct scsi_cmd *cmd)
 {
 	int len = 0, ret = SAM_STAT_CHECK_CONDITION;
@@ -234,15 +250,17 @@ int spc_inquiry(int host_no, struct scsi_cmd *cmd)
 		}
 	}
 
-	if (ret != SAM_STAT_GOOD)
+	if (ret != SAM_STAT_GOOD) {
+		free(data);
 		goto sense;
+	}
 
-	cmd->len = min_t(int, len, scb[4]);
-	cmd->uaddr = (unsigned long) data;
-
+	if (scb[4] < len)
+	    len = scb[4];
 	if (cmd->dev->lun != cmd->dev_id)
 		data[0] = TYPE_NO_LUN;
 
+	spc_return_buf(cmd, data, len);
 	return SAM_STAT_GOOD;
 sense:
 	cmd->len = 0;
@@ -297,9 +315,8 @@ int spc_report_luns(int host_no, struct scsi_cmd *cmd)
 		}
 	}
 
-	cmd->uaddr = (unsigned long)data;
 	*((uint32_t *) data) = __cpu_to_be32(nr_luns * 8);
-	cmd->len = min(oalen, nr_luns * 8 + 8);
+	spc_return_buf(cmd, data, min(oalen, nr_luns * 8 + 8));
 	return SAM_STAT_GOOD;
 sense:
 	cmd->len = 0;
@@ -373,7 +390,7 @@ static int build_mode_page(uint8_t *data, struct mode_pg *pg)
 int spc_mode_sense(int host_no, struct scsi_cmd *cmd)
 {
 	int len = 0;
-	uint8_t *data, *scb, mode6, dbd, pcode, subpcode;
+	uint8_t *data = NULL, *scb, mode6, dbd, pcode, subpcode;
 	uint16_t alloc_len;
 	unsigned char key = ILLEGAL_REQUEST;
 	uint16_t asc = ASC_INVALID_FIELD_IN_CDB;
@@ -436,11 +453,12 @@ int spc_mode_sense(int host_no, struct scsi_cmd *cmd)
 		data[7] = dbd ? 0 : BLOCK_DESCRIPTOR_LEN;
 	}
 
-	cmd->len = len;
-	cmd->uaddr = (unsigned long)data;
+	spc_return_buf(cmd, data, len);
 	return SAM_STAT_GOOD;
 
 sense:
+	if (data)
+		free(data);
 	cmd->len = 0;
 	sense_data_build(cmd, key, asc);
 	return SAM_STAT_CHECK_CONDITION;
diff --git a/usr/spc.h b/usr/spc.h
index dfb8987..766212e 100644
--- a/usr/spc.h
+++ b/usr/spc.h
@@ -1,6 +1,7 @@
 #ifndef __SPC_H
 #define __SPC_H
 
+extern void spc_return_buf(struct scsi_cmd *cmd, void *data, uint32_t len);
 extern int spc_inquiry(int host_no, struct scsi_cmd *cmd);
 extern int spc_report_luns(int host_no, struct scsi_cmd *cmd);
 extern int spc_start_stop(int host_no, struct scsi_cmd *cmd);
-- 
1.5.3.4




More information about the stgt mailing list