Avoid reporting a capacity that is too big if the LIO device block size is larger than the block device block size. Avoid reporting a capacity that is too small if the LIO device block size is smaller than the block device block size. Untested, hence posting this as an RFC. Signed-off-by: Bart Van Assche <bart.vanassche@xxxxxxxxxxx> --- drivers/target/target_core_iblock.c | 78 ++++--------------------------------- 1 file changed, 7 insertions(+), 71 deletions(-) diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 6d88d24..8c78782 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -210,83 +210,19 @@ static void iblock_free_device(struct se_device *dev) call_rcu(&dev->rcu_head, iblock_dev_call_rcu); } +/* + * Return one less than the capacity as a number of blocks. If the block device + * block size and the LIO device block size are different and if the capacity + * is not a multiple of the LIO device block size, round down. + */ static unsigned long long iblock_emulate_read_cap_with_block_size( struct se_device *dev, struct block_device *bd, struct request_queue *q) { - unsigned long long blocks_long = (div_u64(i_size_read(bd->bd_inode), - bdev_logical_block_size(bd)) - 1); - u32 block_size = bdev_logical_block_size(bd); - - if (block_size == dev->dev_attrib.block_size) - return blocks_long; - - switch (block_size) { - case 4096: - switch (dev->dev_attrib.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->dev_attrib.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->dev_attrib.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->dev_attrib.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; - } + unsigned bs = dev->dev_attrib.block_size; - return blocks_long; + return (i_size_read(bd->bd_inode) >> ilog2(bs)) - 1; } static void iblock_complete_cmd(struct se_cmd *cmd) -- 2.1.4 -- To unsubscribe from this list: send the line "unsubscribe target-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html