[PATCH 4/7] [Target_Core_Mod/IBLOCK]: Add 4k sector/block sizeemulation support

From: Nicholas A. Bellinger
Date: Fri Feb 20 2009 - 03:06:24 EST


>From 55077269eecb5b7743bfbbb303547bcb029a91db Mon Sep 17 00:00:00 2001
From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx>
Date: Thu, 19 Feb 2009 19:37:51 -0800
Subject: [PATCH 4/7] [Target_Core_Mod/IBLOCK]: Add 4k sector/block size emulation support

This patch adds support for 4k (and all non 512 byte) sector sizes for the
Target_Core_Mod/ConfigFS interaction with Linux/Block struct block_device objects.

This patch adds iblock_emulate_read_cap_with_block_size() to generate
the total unsigned long long block count for READ_CAPACITY and READ_CAPACITY_16.

Signed-off-by: Nicholas A. Bellinger <nab@xxxxxxxxxxxxxxx>
---
drivers/lio-core/target_core_iblock.c | 101 +++++++++++++++++++++++++++++++--
drivers/lio-core/target_core_iblock.h | 1 -
2 files changed, 95 insertions(+), 7 deletions(-)

diff --git a/drivers/lio-core/target_core_iblock.c b/drivers/lio-core/target_core_iblock.c
index d71d766..bbb8e73 100644
--- a/drivers/lio-core/target_core_iblock.c
+++ b/drivers/lio-core/target_core_iblock.c
@@ -365,25 +365,109 @@ static int iblock_emulate_inquiry (se_task_t *task)
se_location));
}

+static unsigned long long iblock_emulate_read_cap_with_block_size (
+ se_device_t *dev,
+ struct block_device *bd,
+ struct request_queue *q)
+{
+ unsigned long long blocks_long = (get_capacity(bd->bd_disk) - 1);
+
+ if (q->hardsect_size == DEV_ATTRIB(dev)->block_size)
+ return(blocks_long);
+
+ switch (q->hardsect_size) {
+ case 4096:
+ switch (DEV_ATTRIB(dev)->block_size) {
+ case 2048:
+ blocks_long <<= 1;
+ break;
+ case 1024:
+ blocks_long <<= 2;
+ break;
+ case 512:
+ blocks_long <<= 3;
+ default:
+ break;
+ }
+ break;
+ case 2048:
+ switch (DEV_ATTRIB(dev)->block_size) {
+ case 4096:
+ blocks_long >>= 1;
+ break;
+ case 1024:
+ blocks_long <<= 1;
+ break;
+ case 512:
+ blocks_long <<= 2;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 1024:
+ switch (DEV_ATTRIB(dev)->block_size) {
+ case 4096:
+ blocks_long >>= 2;
+ break;
+ case 2048:
+ blocks_long >>= 1;
+ break;
+ case 512:
+ blocks_long <<= 1;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 512:
+ switch (DEV_ATTRIB(dev)->block_size) {
+ case 4096:
+ blocks_long >>= 3;
+ break;
+ case 2048:
+ blocks_long >>= 2;
+ break;
+ case 1024:
+ blocks_long >>= 1;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return(blocks_long);
+}
+
static int iblock_emulate_read_cap (se_task_t *task)
{
iblock_dev_t *ibd = (iblock_dev_t *) task->se_dev->dev_ptr;
struct block_device *bd = ibd->ibd_bd;
- u32 blocks = (get_capacity(bd->bd_disk) - 1);
+ struct request_queue *q = bdev_get_queue(bd);
+ unsigned long long blocks_long = 0;
+ u32 blocks = 0;

- if ((get_capacity(bd->bd_disk) - 1) >= 0x00000000ffffffff)
+ blocks_long = iblock_emulate_read_cap_with_block_size(task->se_dev, bd, q);
+ if (blocks_long >= 0x00000000ffffffff)
blocks = 0xffffffff;
+ else
+ blocks = (u32)blocks_long;

- return(transport_generic_emulate_readcapacity(TASK_CMD(task), blocks, IBLOCK_BLOCKSIZE));
+ return(transport_generic_emulate_readcapacity(TASK_CMD(task), blocks));
}

static int iblock_emulate_read_cap16 (se_task_t *task)
{
iblock_dev_t *ibd = (iblock_dev_t *) task->se_dev->dev_ptr;
struct block_device *bd = ibd->ibd_bd;
- unsigned long long blocks_long = (get_capacity(bd->bd_disk) - 1);
+ struct request_queue *q = bdev_get_queue(bd);
+ unsigned long long blocks_long;

- return(transport_generic_emulate_readcapacity_16(TASK_CMD(task), blocks_long, IBLOCK_BLOCKSIZE));;
+ blocks_long = iblock_emulate_read_cap_with_block_size(task->se_dev, bd, q);
+ return(transport_generic_emulate_readcapacity_16(TASK_CMD(task), blocks_long));
}

static int iblock_emulate_scsi_cdb (se_task_t *task)
@@ -831,7 +915,12 @@ extern unsigned char *iblock_get_cdb (se_task_t *task)

extern u32 iblock_get_blocksize (se_device_t *dev)
{
- return(IBLOCK_BLOCKSIZE);
+ iblock_dev_t *ibd = (iblock_dev_t *) dev->dev_ptr;
+ struct request_queue *q = bdev_get_queue(ibd->ibd_bd);
+ /*
+ * Set via blk_queue_hardsect_size() in drivers/scsi/sd.c:sd_read_capacity()
+ */
+ return(q->hardsect_size);
}

extern u32 iblock_get_device_rev (se_device_t *dev)
diff --git a/drivers/lio-core/target_core_iblock.h b/drivers/lio-core/target_core_iblock.h
index ea5b8f3..ec00140 100644
--- a/drivers/lio-core/target_core_iblock.h
+++ b/drivers/lio-core/target_core_iblock.h
@@ -30,7 +30,6 @@

#define IBLOCK_VERSION "v3.0"

-#define IBLOCK_BLOCKSIZE 512
#define IBLOCK_MAX_SECTORS 128
#define IBLOCK_HBA_QUEUE_DEPTH 512
#define IBLOCK_DEVICE_QUEUE_DEPTH 32
--
1.5.4.1




--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/