[stgt] [PATCH] Fix COMPARE_AND_WRITE but leave it disabled.

Ronnie Sahlberg ronniesahlberg at gmail.com
Fri Dec 7 04:14:48 CET 2012


Fix the compare and write opcode but leave it disabled.
It looks like consumers like vmware may be assuming that IF
compare and write is present and if it works, then the target will also
implement other opcodes like XCOPY etc.

So lets fix the command so that it works, but wait with enabling it
until we have everything else that the main consumer of this rare opcode
expects and wants.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg at gmail.com>
---
 usr/bs_rdwr.c |   21 +++++++++++++++++----
 1 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/usr/bs_rdwr.c b/usr/bs_rdwr.c
index c9ab48d..b59fe7b 100644
--- a/usr/bs_rdwr.c
+++ b/usr/bs_rdwr.c
@@ -73,7 +73,7 @@ static void bs_rdwr_request(struct scsi_cmd *cmd)
 	int do_verify = 0;
 	int i;
 	char *ptr;
-
+	const char *write_buf = NULL;
 	ret = length = 0;
 	key = asc = 0;
 
@@ -104,9 +104,20 @@ static void bs_rdwr_request(struct scsi_cmd *cmd)
 
 		free(tmpbuf);
 
+		write_buf = scsi_get_out_buffer(cmd);
 		goto write;
 	case COMPARE_AND_WRITE:
-		length = scsi_get_out_length(cmd);
+		/* Blocks are transferred twice, first the set that
+		 * we compare to the existing data, and second the set
+		 * to write if the compare was successful.
+		 */
+		length = scsi_get_out_length(cmd) / 2;
+		if (length != cmd->tl) {
+			result = SAM_STAT_CHECK_CONDITION;
+			key = ILLEGAL_REQUEST;
+			asc = ASC_INVALID_FIELD_IN_CDB;
+			break;
+		}
 
 		tmpbuf = malloc(length);
 		if (!tmpbuf) {
@@ -152,6 +163,7 @@ static void bs_rdwr_request(struct scsi_cmd *cmd)
 
 		free(tmpbuf);
 
+		write_buf = scsi_get_out_buffer(cmd) + length;
 		goto write;
 	case SYNCHRONIZE_CACHE:
 	case SYNCHRONIZE_CACHE_16:
@@ -173,9 +185,10 @@ static void bs_rdwr_request(struct scsi_cmd *cmd)
 	case WRITE_10:
 	case WRITE_12:
 	case WRITE_16:
-write:
 		length = scsi_get_out_length(cmd);
-		ret = pwrite64(fd, scsi_get_out_buffer(cmd), length,
+		write_buf = scsi_get_out_buffer(cmd);
+write:
+		ret = pwrite64(fd, write_buf, length,
 			       offset);
 		if (ret == length) {
 			struct mode_pg *pg;
-- 
1.7.3.1

--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the stgt mailing list