Skip to contentSkip to conversation

extracting infos from struct scsi_cmnd

PATCH In review Tommaso Moroni 3 participants 6 messages Nov 27, 2004 – Nov 28, 2004 SCSI

lore
Share & tools
lore
#0 lore raw

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]>
#1 lore raw
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_cmnd the 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
#2 lore raw

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

#3 lore raw

Re: extracting resid from struct scsi_cmnd

Quoted 10 lines · Douglas Gilbert

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.

->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
#4 lore raw

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 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.

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: 2000

So 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;
 	}
 
 	/*
#5 lore raw

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 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.

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: 2000

So 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 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