After reading SBC again it becomes a lot more clear how this opcode works. Reactivate the opcode and implement it properly. Compare the first "number of blocks" from DATA-OUT with the existing content of these blocks on the LUN. If it compare ok, then overwrite these block on the lun with the next "number of blocks" from the DATA-OUT buffer. Signed-off-by: Ronnie Sahlberg <ronniesahlberg@xxxxxxxxx> --- usr/bs_rdwr.c | 21 +++++++++++++++++---- usr/sbc.c | 2 +- 2 files changed, 18 insertions(+), 5 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; diff --git a/usr/sbc.c b/usr/sbc.c index c059c37..d839a8f 100644 --- a/usr/sbc.c +++ b/usr/sbc.c @@ -842,7 +842,7 @@ static struct device_type_template sbc_template = { {spc_illegal_op,}, {sbc_rw, NULL, PR_EA_FA|PR_EA_FN}, - /* {sbc_rw, NULL, PR_EA_FA|PR_EA_FN}, */ + {sbc_rw, NULL, PR_EA_FA|PR_EA_FN}, {spc_illegal_op,}, {sbc_rw, NULL, PR_WE_FA|PR_EA_FA|PR_WE_FN|PR_EA_FN}, {sbc_rw, NULL, PR_EA_FA|PR_EA_FN}, -- 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