All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] scsi: fix scsi_get_lba helper function for pc command
@ 2010-06-02  7:33 FUJITA Tomonori
  2010-06-02  8:14 ` Boaz Harrosh
  2010-06-02 14:07 ` James Bottomley
  0 siblings, 2 replies; 12+ messages in thread
From: FUJITA Tomonori @ 2010-06-02  7:33 UTC (permalink / raw)
  To: James.Bottomley, jaxboe; +Cc: linux-scsi, Sathya.Prakash

This fixes scsi_get_lba() helper function for PC commands.

Only the block layer is supposed to touch rq->__sector. We could
create a new accessor for it. But it seems overdoing a bit? Jens?

=
From: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
Subject: [PATCH] scsi: fix scsi_get_lba helper function for pc command

scsi_get_lba() can be used to get the lba info from
scsi_cmnd. scsi_get_lba() gets the lba info from rq->__sector so
scsi_get_lba() returns a bogus value for PC commands (we don't use
rq->__sector for PC commands).

This patch sets rq->__sector in scsi_setup_blk_pc_cmnd() so that
scsi_get_lba() works with PC commands.

scsi_get_data_transfer_info() is taken from
scsi_debug. scsi_get_data_transfer_info() looks useful for some
(scsi_debug, scsi_trace, libata, etc). So I export it. I'll convert
them to use scsi_get_data_transfer_info().

Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
---
 drivers/scsi/scsi_lib.c  |   54 +++++++++++++++++++++++++++++++++++++++++++++-
 include/scsi/scsi_cmnd.h |    4 +++
 2 files changed, 57 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 1646fe7..b9b7f40 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -19,6 +19,7 @@
 #include <linux/delay.h>
 #include <linux/hardirq.h>
 #include <linux/scatterlist.h>
+#include <asm/unaligned.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -69,6 +70,52 @@ struct kmem_cache *scsi_sdb_cache;
 
 static void scsi_run_queue(struct request_queue *q);
 
+int scsi_get_data_transfer_info(unsigned char *cmd, unsigned long long *lba,
+				unsigned int *num, unsigned int *ei_lba)
+{
+	int ret = 0;
+
+	switch (*cmd) {
+	case VARIABLE_LENGTH_CMD:
+		*lba = get_unaligned_be64(&cmd[12]);
+		*num = get_unaligned_be32(&cmd[28]);
+		*ei_lba = get_unaligned_be32(&cmd[20]);
+		break;
+	case WRITE_16:
+	case READ_16:
+	case VERIFY_16:
+	case WRITE_SAME_16:
+		*lba = get_unaligned_be64(&cmd[2]);
+		*num = get_unaligned_be32(&cmd[10]);
+		break;
+	case WRITE_12:
+	case READ_12:
+	case VERIFY_12:
+		*lba = get_unaligned_be32(&cmd[2]);
+		*num = get_unaligned_be32(&cmd[6]);
+		break;
+	case WRITE_10:
+	case READ_10:
+	case XDWRITEREAD_10:
+	case VERIFY:
+	case WRITE_SAME:
+		*lba = get_unaligned_be32(&cmd[2]);
+		*num = get_unaligned_be16(&cmd[7]);
+		break;
+	case WRITE_6:
+	case READ_6:
+		*lba = (u32)cmd[3] | (u32)cmd[2] << 8 |
+			(u32)(cmd[1] & 0x1f) << 16;
+		*num = (0 == cmd[4]) ? 256 : cmd[4];
+		break;
+	default:
+		ret = -1;
+		break;
+	}
+	return ret;
+}
+EXPORT_SYMBOL(scsi_get_data_transfer_info);
+
 /*
  * Function:	scsi_unprep_request()
  *
@@ -1046,6 +1093,8 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 {
 	struct scsi_cmnd *cmd;
 	int ret = scsi_prep_state_check(sdev, req);
+	unsigned int num, ei_lba;
+	unsigned long long lba;
 
 	if (ret != BLKPREP_OK)
 		return ret;
@@ -1082,7 +1131,10 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req)
 		cmd->sc_data_direction = DMA_TO_DEVICE;
 	else
 		cmd->sc_data_direction = DMA_FROM_DEVICE;
-	
+
+	scsi_get_data_transfer_info(cmd->cmnd, &lba, &num, &ei_lba);
+	req->__sector = lba;
+
 	cmd->transfersize = blk_rq_bytes(req);
 	cmd->allowed = req->retries;
 	return BLKPREP_OK;
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index a5e885a..be3c785 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -151,6 +151,10 @@ extern void scsi_dma_unmap(struct scsi_cmnd *cmd);
 struct scsi_cmnd *scsi_allocate_command(gfp_t gfp_mask);
 void scsi_free_command(gfp_t gfp_mask, struct scsi_cmnd *cmd);
 
+extern int scsi_get_data_transfer_info(unsigned char *cmd,
+				       unsigned long long *lba,
+				       unsigned int *num, unsigned int *ei_lba);
+
 static inline unsigned scsi_sg_count(struct scsi_cmnd *cmd)
 {
 	return cmd->sdb.table.nents;
-- 
1.6.5


^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2010-06-03 11:19 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-02  7:33 [PATCH] scsi: fix scsi_get_lba helper function for pc command FUJITA Tomonori
2010-06-02  8:14 ` Boaz Harrosh
2010-06-02  8:39   ` FUJITA Tomonori
2010-06-02  8:54     ` Boaz Harrosh
2010-06-02  9:05       ` FUJITA Tomonori
2010-06-02  9:23         ` Boaz Harrosh
2010-06-02 13:13         ` Martin K. Petersen
2010-06-03 10:59           ` FUJITA Tomonori
2010-06-03 11:03             ` Prakash, Sathya
2010-06-02 14:07 ` James Bottomley
2010-06-02 14:55   ` Douglas Gilbert
2010-06-03 11:18     ` FUJITA Tomonori

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.