aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/xen-blkfront.c
diff options
context:
space:
mode:
authorStefan Bader <stefan.bader@canonical.com>2013-05-13 10:28:15 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2013-06-07 17:05:53 -0400
commit7c4d7d710f7eb499ec483f25acc28b53adaa3260 (patch)
tree4ad0e3765e0f1f0f00f1782f264565e0e02e4666 /drivers/block/xen-blkfront.c
parent1d1996509cd3f90551f4460a68aaf3dc940a05e3 (diff)
xen/blkback: Use physical sector size for setup
Currently xen-blkback passes the logical sector size over xenbus and xen-blkfront sets up the paravirt disk with that logical block size. But newer drives usually have the logical sector size set to 512 for compatibility reasons and would show the actual sector size only in physical sector size. This results in the device being partitioned and accessed in dom0 with the correct sector size, but the guest thinks 512 bytes is the correct block size. And that results in poor performance. To fix this, blkback gets modified to pass also physical-sector-size over xenbus and blkfront to use both values to set up the paravirt disk. I did not just change the passed in sector-size because I am not sure having a bigger logical sector size than the physical one is valid (and that would happen if a newer dom0 kernel hits an older domU kernel). Also this way a domU set up before should still be accessible (just some tools might detect the unaligned setup). [v2: Make xenbus write failure non-fatal] [v3: Use xenbus_scanf instead of xenbus_gather] [v4: Rebased against segment changes] Signed-off-by: Stefan Bader <stefan.bader@canonical.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'drivers/block/xen-blkfront.c')
-rw-r--r--drivers/block/xen-blkfront.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 08bdfc3b2de2..1a0f67c10ec7 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -609,6 +609,7 @@ wait:
609} 609}
610 610
611static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size, 611static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size,
612 unsigned int physical_sector_size,
612 unsigned int segments) 613 unsigned int segments)
613{ 614{
614 struct request_queue *rq; 615 struct request_queue *rq;
@@ -631,6 +632,7 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size,
631 632
632 /* Hard sector size and max sectors impersonate the equiv. hardware. */ 633 /* Hard sector size and max sectors impersonate the equiv. hardware. */
633 blk_queue_logical_block_size(rq, sector_size); 634 blk_queue_logical_block_size(rq, sector_size);
635 blk_queue_physical_block_size(rq, physical_sector_size);
634 blk_queue_max_hw_sectors(rq, 512); 636 blk_queue_max_hw_sectors(rq, 512);
635 637
636 /* Each segment in a request is up to an aligned page in size. */ 638 /* Each segment in a request is up to an aligned page in size. */
@@ -737,7 +739,8 @@ static char *encode_disk_name(char *ptr, unsigned int n)
737 739
738static int xlvbd_alloc_gendisk(blkif_sector_t capacity, 740static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
739 struct blkfront_info *info, 741 struct blkfront_info *info,
740 u16 vdisk_info, u16 sector_size) 742 u16 vdisk_info, u16 sector_size,
743 unsigned int physical_sector_size)
741{ 744{
742 struct gendisk *gd; 745 struct gendisk *gd;
743 int nr_minors = 1; 746 int nr_minors = 1;
@@ -804,7 +807,7 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
804 gd->driverfs_dev = &(info->xbdev->dev); 807 gd->driverfs_dev = &(info->xbdev->dev);
805 set_capacity(gd, capacity); 808 set_capacity(gd, capacity);
806 809
807 if (xlvbd_init_blk_queue(gd, sector_size, 810 if (xlvbd_init_blk_queue(gd, sector_size, physical_sector_size,
808 info->max_indirect_segments ? : 811 info->max_indirect_segments ? :
809 BLKIF_MAX_SEGMENTS_PER_REQUEST)) { 812 BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
810 del_gendisk(gd); 813 del_gendisk(gd);
@@ -1698,6 +1701,7 @@ static void blkfront_connect(struct blkfront_info *info)
1698{ 1701{
1699 unsigned long long sectors; 1702 unsigned long long sectors;
1700 unsigned long sector_size; 1703 unsigned long sector_size;
1704 unsigned int physical_sector_size;
1701 unsigned int binfo; 1705 unsigned int binfo;
1702 int err; 1706 int err;
1703 int barrier, flush, discard, persistent; 1707 int barrier, flush, discard, persistent;
@@ -1747,6 +1751,16 @@ static void blkfront_connect(struct blkfront_info *info)
1747 return; 1751 return;
1748 } 1752 }
1749 1753
1754 /*
1755 * physcial-sector-size is a newer field, so old backends may not
1756 * provide this. Assume physical sector size to be the same as
1757 * sector_size in that case.
1758 */
1759 err = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
1760 "physical-sector-size", "%u", &physical_sector_size);
1761 if (err != 1)
1762 physical_sector_size = sector_size;
1763
1750 info->feature_flush = 0; 1764 info->feature_flush = 0;
1751 info->flush_op = 0; 1765 info->flush_op = 0;
1752 1766
@@ -1800,7 +1814,8 @@ static void blkfront_connect(struct blkfront_info *info)
1800 return; 1814 return;
1801 } 1815 }
1802 1816
1803 err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size); 1817 err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size,
1818 physical_sector_size);
1804 if (err) { 1819 if (err) {
1805 xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s", 1820 xenbus_dev_fatal(info->xbdev, err, "xlvbd_add at %s",
1806 info->xbdev->otherend); 1821 info->xbdev->otherend);