Skip to contentSkip to conversation

scsi-mq: fix requests that use a separate CDB buffer

PATCH In review Tony Battersby 2 participants 5 messages Aug 22, 2014 – Aug 25, 2014

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 scsi-mq: fix requests that use a separate CDB buffer

This patch fixes code such as the following with scsi-mq enabled:

    rq = blk_get_request(...);
    blk_rq_set_block_pc(rq);

    rq->cmd = my_cmd_buffer; /* separate CDB buffer */

    blk_execute_rq_nowait(...);

Code like this appears in e.g. sg_start_req() in drivers/scsi/sg.c (for large CDBs only). Without this patch, scsi_mq_prep_fn() will set rq->cmd back to rq->__cmd, causing the wrong CDB to be sent to the device.

---

For inclusion in 3.17 only.

block/blk-core.c +0 -1
diff -urpN linux-3.17.0-rc1-a/block/blk-core.c linux-3.17.0-rc1-b/block/blk-core.c
@@ -1252,7 +1252,6 @@ void blk_rq_set_block_pc(struct request 
 	rq->__sector = (sector_t) -1;
 	rq->bio = rq->biotail = NULL;
 	memset(rq->__cmd, 0, sizeof(rq->__cmd));
-	rq->cmd = rq->__cmd;
 }
 EXPORT_SYMBOL(blk_rq_set_block_pc);
 
block/blk-mq.c +2 -0
diff -urpN linux-3.17.0-rc1-a/block/blk-mq.c linux-3.17.0-rc1-b/block/blk-mq.c
@@ -172,6 +172,8 @@ static void blk_mq_rq_ctx_init(struct re
 	/* tag was already set */
 	rq->errors = 0;
 
+	rq->cmd = rq->__cmd;
+
 	rq->extra_len = 0;
 	rq->sense_len = 0;
 	rq->resid_len = 0;
drivers/scsi/scsi_lib.c +0 -1
diff -urpN linux-3.17.0-rc1-a/drivers/scsi/scsi_lib.c linux-3.17.0-rc1-b/drivers/scsi/scsi_lib.c
@@ -1808,7 +1808,6 @@ static int scsi_mq_prep_fn(struct reques
 
 	cmd->tag = req->tag;
 
-	req->cmd = req->__cmd;
 	cmd->cmnd = req->cmd;
 	cmd->prot_op = SCSI_PROT_NORMAL;
 
#1 lore raw
Quoted 9 lines · Tony Battersby

This patch fixes code such as the following with scsi-mq enabled:

     rq = blk_get_request(...);
     blk_rq_set_block_pc(rq);

     rq->cmd = my_cmd_buffer; /* separate CDB buffer */

     blk_execute_rq_nowait(...);
Quoted 3 lines

Code like this appears in e.g. sg_start_req() in drivers/scsi/sg.c (for large CDBs only). Without this patch, scsi_mq_prep_fn() will set rq->cmd back to rq->__cmd, causing the wrong CDB to be sent to the device.

Still looking at this one. 'sg_write_same --32' is my tool of choice. The target is scsi_debug which needs dif=2 (because mkp read the draft and only allows WRITE SAME(32) when the protection_level=2). Turned on command tracing and this is what I saw:

sd 7:0:0:0: scsi_debug: cmd 9e 10 00 00 00 00 00 00 00 00 00 00 00 20 00 00
sd 7:0:0:0: scsi_debug: cmd 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 24 6b d3 00 88 ff ff 20 00 c7 e8 00 00 00 00

So the WS(32) command did get through, it is the second command that arrived on its tail that is a worry. So yes, IMO it is broken.

Now the >16 byte cdb length in the sg driver introduced in lk 3.17-rc1 was copied directly from the bsg driver which has had that capability for some time. Since your patch touches two files in drivers/block I'm wondering the bsg driver's

Quoted 1 line

16 byte cdb length capability is broken in

lk 3.16 ?

Doug Gilbert

#2 lore raw
Quoted 20 lines · Douglas Gilbert
Quoted 9 lines · Tony Battersby

This patch fixes code such as the following with scsi-mq enabled:

     rq = blk_get_request(...);
     blk_rq_set_block_pc(rq);

     rq->cmd = my_cmd_buffer; /* separate CDB buffer */

     blk_execute_rq_nowait(...);
Quoted 3 lines

Code like this appears in e.g. sg_start_req() in drivers/scsi/sg.c (for large CDBs only). Without this patch, scsi_mq_prep_fn() will set rq->cmd back to rq->__cmd, causing the wrong CDB to be sent to the device.

Still looking at this one. 'sg_write_same --32' is my tool of choice. The target is scsi_debug which needs dif=2 (because mkp read the draft and only allows WRITE SAME(32) when the protection_level=2). Turned on command tracing and this is what I saw:

Quoted 7 lines

sd 7:0:0:0: scsi_debug: cmd 9e 10 00 00 00 00 00 00 00 00 00 00 00 20 00 00 sd 7:0:0:0: scsi_debug: cmd 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 24 6b d3 00 88 ff ff 20 00 c7 e8 00 00 00 00

So the WS(32) command did get through, it is the second command that arrived on its tail that is a worry. So yes, IMO it is broken.

Got that wrong, that is a READ CAPACITY(16) that got through properly (issued by sg_write_same) followed by a 32 byte command of random bytes instead of the requested WS(32), the first 6 bytes of which will cause it to be parsed as a TEST UNIT READY.

Quoted 17 lines

Now the >16 byte cdb length in the sg driver
introduced in lk 3.17-rc1 was copied directly
from the bsg driver which has had that capability
for some time. Since your patch touches two files
in drivers/block I'm wondering the bsg driver's

Quoted 1 line

16 byte cdb length capability is broken in

lk 3.16 ?

Doug Gilbert

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

Tested-by on v1 1/1
#3 lore raw
In reply to Tony Battersby
Quoted 9 lines · Tony Battersby

This patch fixes code such as the following with scsi-mq enabled:

     rq = blk_get_request(...);
     blk_rq_set_block_pc(rq);

     rq->cmd = my_cmd_buffer; /* separate CDB buffer */

     blk_execute_rq_nowait(...);
Quoted 5 lines

Code like this appears in e.g. sg_start_req() in drivers/scsi/sg.c (for large CDBs only). Without this patch, scsi_mq_prep_fn() will set rq->cmd back to rq->__cmd, causing the wrong CDB to be sent to the device.

Patch tested on lk 3.17-rc1 with the sg driver using the READ(32) command.

Quoted 1 line

For inclusion in 3.17 only.

May want to check if blk-mq work in lk 3.16 and earlier breaks the bsg driver's capability to send SCSI cdbs that are longer than 16 bytes.

Quoted 36 lines

diff -urpN linux-3.17.0-rc1-a/block/blk-core.c linux-3.17.0-rc1-b/block/blk-core.c

block/blk-core.c +0 -1
@@ -1252,7 +1252,6 @@ void blk_rq_set_block_pc(struct request
  	rq->__sector = (sector_t) -1;
  	rq->bio = rq->biotail = NULL;
  	memset(rq->__cmd, 0, sizeof(rq->__cmd));
-	rq->cmd = rq->__cmd;
  }
  EXPORT_SYMBOL(blk_rq_set_block_pc);
 

diff -urpN linux-3.17.0-rc1-a/block/blk-mq.c linux-3.17.0-rc1-b/block/blk-mq.c

block/blk-mq.c +2 -0
@@ -172,6 +172,8 @@ static void blk_mq_rq_ctx_init(struct re
  	/* tag was already set */
  	rq->errors = 0;
 
+	rq->cmd = rq->__cmd;
+
  	rq->extra_len = 0;
  	rq->sense_len = 0;
  	rq->resid_len = 0;

diff -urpN linux-3.17.0-rc1-a/drivers/scsi/scsi_lib.c linux-3.17.0-rc1-b/drivers/scsi/scsi_lib.c

drivers/scsi/scsi_lib.c +0 -2
@@ -1808,7 +1808,6 @@ static int scsi_mq_prep_fn(struct reques
 
  	cmd->tag = req->tag;
 
-	req->cmd = req->__cmd;
  	cmd->cmnd = req->cmd;
  	cmd->prot_op = SCSI_PROT_NORMAL;
 
 
--
#4 lore raw
Quoted 6 lines · Douglas Gilbert
Quoted 1 line

For inclusion in 3.17 only.

May want to check if blk-mq work in lk 3.16 and earlier breaks the bsg driver's capability to send SCSI cdbs that are longer than 16 bytes.

I think 3.16 and earlier are OK. The problem was caused by scsi_mq_prep_fn(), which is new in 3.17.

Thanks for testing.

Tony