[PATCH] Fix COMPARE_AND_WRITE but leave it disabled.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---
 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@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux SCSI]     [Linux RAID]     [Linux Clusters]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]

  Powered by Linux