Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

target: Pass through I/O topology for block backstores

In addition to block size (already implemented), passing through
alignment offset, logical-to-phys block exponent, I/O granularity and
optimal I/O length will allow initiators to properly handle layout on
LUNs with 4K block sizes.

Tested with various weird values via scsi_debug module.

One thing to look at with this patch is the new block limits values --
instead of granularity 1 optimal 8192, Lio will now be returning whatever
the block device says, which may affect performance.

Signed-off-by: Andy Grover <agrover@redhat.com>
Acked-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>

authored by

Andy Grover and committed by
Nicholas Bellinger
7f7caf6a f01b9f73

+68 -3
+43
drivers/target/target_core_iblock.c
··· 710 710 return iblock_emulate_read_cap_with_block_size(dev, bd, q); 711 711 } 712 712 713 + static sector_t iblock_get_alignment_offset_lbas(struct se_device *dev) 714 + { 715 + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); 716 + struct block_device *bd = ib_dev->ibd_bd; 717 + int ret; 718 + 719 + ret = bdev_alignment_offset(bd); 720 + if (ret == -1) 721 + return 0; 722 + 723 + /* convert offset-bytes to offset-lbas */ 724 + return ret / bdev_logical_block_size(bd); 725 + } 726 + 727 + static unsigned int iblock_get_lbppbe(struct se_device *dev) 728 + { 729 + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); 730 + struct block_device *bd = ib_dev->ibd_bd; 731 + int logs_per_phys = bdev_physical_block_size(bd) / bdev_logical_block_size(bd); 732 + 733 + return ilog2(logs_per_phys); 734 + } 735 + 736 + static unsigned int iblock_get_io_min(struct se_device *dev) 737 + { 738 + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); 739 + struct block_device *bd = ib_dev->ibd_bd; 740 + 741 + return bdev_io_min(bd); 742 + } 743 + 744 + static unsigned int iblock_get_io_opt(struct se_device *dev) 745 + { 746 + struct iblock_dev *ib_dev = IBLOCK_DEV(dev); 747 + struct block_device *bd = ib_dev->ibd_bd; 748 + 749 + return bdev_io_opt(bd); 750 + } 751 + 713 752 static struct sbc_ops iblock_sbc_ops = { 714 753 .execute_rw = iblock_execute_rw, 715 754 .execute_sync_cache = iblock_execute_sync_cache, ··· 788 749 .show_configfs_dev_params = iblock_show_configfs_dev_params, 789 750 .get_device_type = sbc_get_device_type, 790 751 .get_blocks = iblock_get_blocks, 752 + .get_alignment_offset_lbas = iblock_get_alignment_offset_lbas, 753 + .get_lbppbe = iblock_get_lbppbe, 754 + .get_io_min = iblock_get_io_min, 755 + .get_io_opt = iblock_get_io_opt, 791 756 .get_write_cache = iblock_get_write_cache, 792 757 }; 793 758
+11 -1
drivers/target/target_core_sbc.c
··· 105 105 buf[9] = (dev->dev_attrib.block_size >> 16) & 0xff; 106 106 buf[10] = (dev->dev_attrib.block_size >> 8) & 0xff; 107 107 buf[11] = dev->dev_attrib.block_size & 0xff; 108 + 109 + if (dev->transport->get_lbppbe) 110 + buf[13] = dev->transport->get_lbppbe(dev) & 0x0f; 111 + 112 + if (dev->transport->get_alignment_offset_lbas) { 113 + u16 lalba = dev->transport->get_alignment_offset_lbas(dev); 114 + buf[14] = (lalba >> 8) & 0x3f; 115 + buf[15] = lalba & 0xff; 116 + } 117 + 108 118 /* 109 119 * Set Thin Provisioning Enable bit following sbc3r22 in section 110 120 * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled. 111 121 */ 112 122 if (dev->dev_attrib.emulate_tpu || dev->dev_attrib.emulate_tpws) 113 - buf[14] = 0x80; 123 + buf[14] |= 0x80; 114 124 115 125 rbuf = transport_kmap_data_sg(cmd); 116 126 if (rbuf) {
+9 -2
drivers/target/target_core_spc.c
··· 452 452 struct se_device *dev = cmd->se_dev; 453 453 u32 max_sectors; 454 454 int have_tp = 0; 455 + int opt, min; 455 456 456 457 /* 457 458 * Following spc3r22 section 6.5.3 Block Limits VPD page, when ··· 476 475 /* 477 476 * Set OPTIMAL TRANSFER LENGTH GRANULARITY 478 477 */ 479 - put_unaligned_be16(1, &buf[6]); 478 + if (dev->transport->get_io_min && (min = dev->transport->get_io_min(dev))) 479 + put_unaligned_be16(min / dev->dev_attrib.block_size, &buf[6]); 480 + else 481 + put_unaligned_be16(1, &buf[6]); 480 482 481 483 /* 482 484 * Set MAXIMUM TRANSFER LENGTH ··· 491 487 /* 492 488 * Set OPTIMAL TRANSFER LENGTH 493 489 */ 494 - put_unaligned_be32(dev->dev_attrib.optimal_sectors, &buf[12]); 490 + if (dev->transport->get_io_opt && (opt = dev->transport->get_io_opt(dev))) 491 + put_unaligned_be32(opt / dev->dev_attrib.block_size, &buf[12]); 492 + else 493 + put_unaligned_be32(dev->dev_attrib.optimal_sectors, &buf[12]); 495 494 496 495 /* 497 496 * Exit now if we don't support TP.
+5
include/target/target_core_backend.h
··· 34 34 sense_reason_t (*parse_cdb)(struct se_cmd *cmd); 35 35 u32 (*get_device_type)(struct se_device *); 36 36 sector_t (*get_blocks)(struct se_device *); 37 + sector_t (*get_alignment_offset_lbas)(struct se_device *); 38 + /* lbppbe = logical blocks per physical block exponent. see SBC-3 */ 39 + unsigned int (*get_lbppbe)(struct se_device *); 40 + unsigned int (*get_io_min)(struct se_device *); 41 + unsigned int (*get_io_opt)(struct se_device *); 37 42 unsigned char *(*get_sense_buffer)(struct se_cmd *); 38 43 bool (*get_write_cache)(struct se_device *); 39 44 };