extracting infos from struct scsi_cmnd
Hi!
I'm writing a module for the 2.6.9 kernel which tracks accesses on a usb-storage device; in particular I'm interested in extracting from a struct scsi_cmnd the data read/written and the associated sector.
The code I'vr written till now looks like the following:
struct scsi_cmnd * cmd;
[...]
if (cmd->use_sg == 0)
{
buf = cmd->buffer;
buflen = cmd->bufflen;
sector = cmd->request->sector;
} else {
struct scatterlist * sl = (struct scatterlist *) cmd->buffer;
for (i = 0; i < cmd->use_sg; i++)
{
buf = page_address(sl[i].page) + sl[i].offset;
buflen = sl[i].length;
/* sector? */
}
}Is it correct?
Where can I find the sector involved in the operation if the scatter-gather is used?
Thank you in advance
Signature · 1 line
Tommaso Moroni <[email protected]>
Quoted 10 lines · Tommaso Moroni
Hi!
I'm writing a module for the 2.6.9 kernel which tracks accesses on a usb-storage device; in particular I'm interested in extracting from a struct
scsi_cmndthe data read/written and the associated sector.The code I'vr written till now looks like the following:
Quoted 7 lines
struct
scsi_cmnd* cmd;
[...]
if (cmd->use_sg== 0){ buf = cmd->buffer; buflen = cmd->bufflen; sector = cmd->request->sector;
->request_bufflen and ->request_buffer.
Quoted 9 lines
} else {
struct scatterlist * sl = (struct scatterlist *) cmd->buffer;
for (i = 0; i < cmd->use_sg; i++)
{
buf = page_address(sl[i].page) + sl[i].offset;
buflen = sl[i].length;
/* sector? */
}
}This only works on non-highmem pages, you should use kmap/kmap_atomic instead.
Quoted 3 lines
Is it correct?
Where can I find the sector involved in the operation if the scatter-gather is used?
It's ->request->sector as well. The total length is just the sum of the sg elements.
Signature · 1 line
Jens Axboe
extracting resid from struct scsi_cmnd
Jens,
While on the subject of extracting info from struct scsi_cmnd I have noticed that scsi_cmnd::resid doesn't make it into sg_io_hdr::resid in the block layer SG_IO implementation. "rq->data_len" is put there instead and it invariably has a value of 0.
"struct request" does not have a 'resid' field which is defined as the number of bytes requested to be transferred less the actual number transferred.
Doug Gilbert
Re: extracting resid from struct scsi_cmnd
Quoted 10 lines · Douglas Gilbert
Jens,
While on the subject of extracting info from structscsi_cmndI have noticed thatscsi_cmnd::residdoesn't make it intosg_io_hdr::residin the block layerSG_IOimplementation. "rq->data_len" is put there instead and it invariably has a value of 0."struct request" does not have a 'resid' field which is defined as the number of bytes requested to be transferred less the actual number transferred.
->data_len is that value, after execution of the request. If rq->data_len == 0 for a SCSI request that with residual bytes, then that's a bug.
Signature · 1 line
Jens Axboe
PATCH 1/1 extracting resid from struct scsi_cmnd
Quoted 9 lines · Jens Axboe
Quoted 7 lines · Douglas Gilbert
Jens,
While on the subject of extracting info from structscsi_cmndI have noticed thatscsi_cmnd::residdoesn't make it intosg_io_hdr::residin the block layerSG_IOimplementation. "rq->data_len" is put there instead and it invariably has a value of 0.
Quoted 7 lines
Quoted 3 lines
"struct request" does not have a 'resid' field which is defined as the number of bytes requested to be transferred less the actual number transferred.
->data_len is that value, after execution of the request. If
rq->data_len== 0 for a SCSI request that with residual bytes, then that's a bug.
Jens,
Ok, it looks like a bug then. Here is an example with the scsi_debug version I just sent to this list and a recent sg3_utils (e.g. v1.11 beta at the top of http://www.torque.net/sg ). That scsi_debug version sets resid and sg3_utils reports resid != 0 when the verbose flag is given.
Here is what I am seeing:
# sg_inq -v /dev/sg0
inquiry cdb: 12 00 00 00 24 00
...
Product identification: scsi_debug
Product revision level: 0004
inquiry cdb: 12 01 00 00 fc 00
inquiry: resid=124
inquiry cdb: 12 01 80 00 fc 00
inquiry: resid=124
Unit serial number: 2000# sg_inq -v /dev/sda
inquiry cdb: 12 00 00 00 24 00
...
Product identification: scsi_debug
Product revision level: 0004
inquiry cdb: 12 01 00 00 fc 00
inquiry cdb: 12 01 80 00 fc 00
Unit serial number: 2000So the sg driver indicates that of the 252 bytes requested (for VPD pages 0x0 and 0x80) only 128 bytes were returned [and 128 bytes is an over-allowance by scsi_debug for those pages]. The sd driver remains silent implying resid is 0 .
rq->data_len is only written in one place in the scsi mid level (in scsi_io_completion() inside scsi_lib.c). The attached patch places cmd->resid into rq->data_len (rather than decrementing it by cmd->bufflen) and fixes the problem shown above. I then built a file system on the scsi_debug virtual disk and copied files to and from it and there were no ill effects.
Changelog:
- during successful command completion place resid from SCSI LLDs into request::data_len so that block SG_IO ioctl reports resid
Doug Gilbert
drivers/scsi/scsi_lib.c2610rc2resid renamed from drivers/scsi/scsi_lib.c +1 -1
@@ -728,7 +728,7 @@ req->sense_len = len; } } else - req->data_len -= cmd->bufflen; + req->data_len = cmd->resid; } /*
Re: [PATCH] extracting resid from struct scsi_cmnd
Quoted 74 lines · Douglas Gilbert
Quoted 9 lines · Jens Axboe
Quoted 7 lines · Douglas Gilbert
Jens,
While on the subject of extracting info from structscsi_cmndI have noticed thatscsi_cmnd::residdoesn't make it intosg_io_hdr::residin the block layerSG_IOimplementation. "rq->data_len" is put there instead and it invariably has a value of 0.Quoted 7 lines
Quoted 3 lines
"struct request" does not have a 'resid' field which is defined as the number of bytes requested to be transferred less the actual number transferred.
->data_len is that value, after execution of the request. If
rq->data_len== 0 for a SCSI request that with residual bytes, then that's a bug.Jens,
Ok, it looks like a bug then. Here is an example with thescsi_debugversion I just sent to this list and a recentsg3_utils(e.g. v1.11 beta at the top of http://www.torque.net/sg ). Thatscsi_debugversion sets resid andsg3_utilsreports resid != 0 when the verbose flag is given.Here is what I am seeing:
# sg_inq -v /dev/sg0 inquiry cdb: 12 00 00 00 24 00 ... Product identification: scsi_debug Product revision level: 0004 inquiry cdb: 12 01 00 00 fc 00 inquiry: resid=124 inquiry cdb: 12 01 80 00 fc 00 inquiry: resid=124 Unit serial number: 2000# sg_inq -v /dev/sda inquiry cdb: 12 00 00 00 24 00 ... Product identification: scsi_debug Product revision level: 0004 inquiry cdb: 12 01 00 00 fc 00 inquiry cdb: 12 01 80 00 fc 00 Unit serial number: 2000So the sg driver indicates that of the 252 bytes requested (for VPD pages
0x0and0x80) only 128 bytes were returned [and 128 bytes is an over-allowance byscsi_debugfor those pages]. The sd driver remains silent implying resid is 0 .
rq->data_lenis only written in one place in the scsi mid level (inscsi_io_completion()insidescsi_lib.c). The attached patch placescmd->residintorq->data_len(rather than decrementing it bycmd->bufflen) and fixes the problem shown above. I then built a file system on thescsi_debugvirtual disk and copied files to and from it and there were no ill effects.Changelog:
- during successful command completion place resid from SCSI LLDs intorequest::data_lenso that blockSG_IOioctl reports residDoug Gilbert
drivers/scsi/scsi_lib.c2610rc2resid line 734
Quoted 8 lines
drivers/scsi/scsi_lib.c2610rc2resid renamed from drivers/scsi/scsi_lib.c +1
-1@@ -728,7 +728,7 @@ req->sense_len = len; } } else - req->data_len -= cmd->bufflen; + req->data_len = cmd->resid; } /*
Patch looks correct, thanks Doug.
Signature · 1 line
Jens Axboe