aboutsummaryrefslogtreecommitdiff
path: root/hw/virtio-blk.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2010-03-04 14:20:17 +0100
committerAnthony Liguori <aliguori@us.ibm.com>2010-03-17 10:42:27 -0500
commit8cfacf079047c50d272ce64e45a78d816db8b36e (patch)
tree4ef370b2b6c6946af66e9bcdfa013a1e93b5079c /hw/virtio-blk.c
parent702f3e0fb52c124c07f215426eeadb70a716643f (diff)
block: add logical_block_size property
Add a logical block size attribute as various guest side tools only increase the filesystem sector size based on it, not the advisory physical block size. For scsi we already have support for a different logical block size in place for CDROMs that we can built upon. Only my recent block device characteristics VPD page needs some fixups. Note that we leave the logial block size for CDROMs hardcoded as the 2k value is expected for it in general. For virtio-blk we already have a feature flag claiming to support a variable logical block size that was added for the s390 kuli hypervisor. Interestingly it does not actually change the units in which the protocol works, which is still fixed at 512 bytes, but only communicates a different minimum I/O granularity. So all we need to do in virtio is to add a trap for unaligned I/O and round down the device size to the next multiple of the logical block size. IDE does not support any other logical block size than 512 bytes. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'hw/virtio-blk.c')
-rw-r--r--hw/virtio-blk.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 8939bb2529..9915840887 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -27,6 +27,7 @@ typedef struct VirtIOBlock
void *rq;
QEMUBH *bh;
BlockConf *conf;
+ unsigned short sector_mask;
} VirtIOBlock;
static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev)
@@ -250,6 +251,11 @@ static void virtio_blk_handle_flush(VirtIOBlockReq *req)
static void virtio_blk_handle_write(BlockRequest *blkreq, int *num_writes,
VirtIOBlockReq *req, BlockDriverState **old_bs)
{
+ if (req->out->sector & req->dev->sector_mask) {
+ virtio_blk_rw_complete(req, -EIO);
+ return;
+ }
+
if (req->dev->bs != *old_bs || *num_writes == 32) {
if (*old_bs != NULL) {
do_multiwrite(*old_bs, blkreq, *num_writes);
@@ -272,6 +278,11 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
{
BlockDriverAIOCB *acb;
+ if (req->out->sector & req->dev->sector_mask) {
+ virtio_blk_rw_complete(req, -EIO);
+ return;
+ }
+
acb = bdrv_aio_readv(req->dev->bs, req->out->sector, &req->qiov,
req->qiov.size / 512, virtio_blk_rw_complete, req);
if (!acb) {
@@ -404,12 +415,13 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
stl_raw(&blkcfg.seg_max, 128 - 2);
stw_raw(&blkcfg.cylinders, cylinders);
blkcfg.heads = heads;
- blkcfg.sectors = secs;
+ blkcfg.sectors = secs & ~s->sector_mask;
+ blkcfg.blk_size = s->conf->logical_block_size;
blkcfg.size_max = 0;
blkcfg.physical_block_exp = get_physical_block_exp(s->conf);
blkcfg.alignment_offset = 0;
- blkcfg.min_io_size = s->conf->min_io_size / 512;
- blkcfg.opt_io_size = s->conf->opt_io_size / 512;
+ blkcfg.min_io_size = s->conf->min_io_size / blkcfg.blk_size;
+ blkcfg.opt_io_size = s->conf->opt_io_size / blkcfg.blk_size;
memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
}
@@ -420,6 +432,7 @@ static uint32_t virtio_blk_get_features(VirtIODevice *vdev, uint32_t features)
features |= (1 << VIRTIO_BLK_F_SEG_MAX);
features |= (1 << VIRTIO_BLK_F_GEOMETRY);
features |= (1 << VIRTIO_BLK_F_TOPOLOGY);
+ features |= (1 << VIRTIO_BLK_F_BLK_SIZE);
if (bdrv_enable_write_cache(s->bs))
features |= (1 << VIRTIO_BLK_F_WCACHE);
@@ -479,6 +492,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
s->bs = conf->dinfo->bdrv;
s->conf = conf;
s->rq = NULL;
+ s->sector_mask = (s->conf->logical_block_size / 512) - 1;
bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
bdrv_set_geometry_hint(s->bs, cylinders, heads, secs);