qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] block: add logical_block_size property


From: Kevin Wolf
Subject: Re: [Qemu-devel] [PATCH] block: add logical_block_size property
Date: Fri, 05 Mar 2010 10:26:21 +0100
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.7) Gecko/20100120 Fedora/3.0.1-1.fc12 Thunderbird/3.0.1

Am 04.03.2010 14:20, schrieb Christoph Hellwig:
> 
> 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 <address@hidden>
> 
> Index: qemu/block_int.h
> ===================================================================
> --- qemu.orig/block_int.h     2010-03-03 19:16:13.408253228 +0100
> +++ qemu/block_int.h  2010-03-03 19:16:43.030003751 +0100
> @@ -209,6 +209,7 @@ struct DriveInfo;
>  typedef struct BlockConf {
>      struct DriveInfo *dinfo;
>      uint16_t physical_block_size;
> +    uint16_t logical_block_size;
>      uint16_t min_io_size;
>      uint32_t opt_io_size;
>  } BlockConf;
> @@ -226,6 +227,8 @@ static inline unsigned int get_physical_
>  
>  #define DEFINE_BLOCK_PROPERTIES(_state, _conf)                          \
>      DEFINE_PROP_DRIVE("drive", _state, _conf.dinfo),                    \
> +    DEFINE_PROP_UINT16("logical_block_size", _state,                    \
> +                       _conf.logical_block_size, 512),                  \
>      DEFINE_PROP_UINT16("physical_block_size", _state,                   \
>                         _conf.physical_block_size, 512),                 \
>      DEFINE_PROP_UINT16("min_io_size", _state, _conf.min_io_size, 512),  \
> Index: qemu/hw/scsi-disk.c
> ===================================================================
> --- qemu.orig/hw/scsi-disk.c  2010-03-03 19:16:13.419254346 +0100
> +++ qemu/hw/scsi-disk.c       2010-03-03 19:16:43.031004240 +0100
> @@ -397,8 +397,10 @@ static int scsi_disk_emulate_inquiry(SCS
>          }
>          case 0xb0: /* block device characteristics */
>          {
> -            unsigned int min_io_size = s->qdev.conf.min_io_size >> 9;
> -            unsigned int opt_io_size = s->qdev.conf.opt_io_size >> 9;
> +            unsigned int min_io_size =
> +                    s->qdev.conf.min_io_size / s->qdev.blocksize;
> +            unsigned int opt_io_size =
> +                    s->qdev.conf.opt_io_size / s->qdev.blocksize;
>  
>              /* required VPD size with unmap support */
>              outbuf[3] = buflen = 0x3c;
> @@ -1028,11 +1030,12 @@ static int scsi_disk_initfn(SCSIDevice *
>      s->bs = s->qdev.conf.dinfo->bdrv;
>  
>      if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
> -        s->cluster_size = 4;
> +        s->qdev.blocksize = 2048;
>      } else {
> -        s->cluster_size = 1;
> +        s->qdev.blocksize = s->qdev.conf.logical_block_size;
>      }
> -    s->qdev.blocksize = 512 * s->cluster_size;
> +    s->cluster_size = s->qdev.blocksize / 512;
> +
>      s->qdev.type = TYPE_DISK;
>      bdrv_get_geometry(s->bs, &nb_sectors);
>      nb_sectors /= s->cluster_size;
> Index: qemu/hw/virtio-blk.c
> ===================================================================
> --- qemu.orig/hw/virtio-blk.c 2010-03-03 19:16:13.426273971 +0100
> +++ qemu/hw/virtio-blk.c      2010-03-03 19:35:16.636028605 +0100
> @@ -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(Virt
>  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(VirtI
>  {
>      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(Vir
>      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(
>      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(DeviceStat
>      s->bs = conf->dinfo->bdrv;
>      s->conf = conf;
>      s->rq = NULL;
> +    s->sector_mask = (s->conf->logical_block_size / 512) - 1;

Is there a check anywhere that the user didn't give us an odd block
size? We could get an interesting bit mask otherwise.

Kevin




reply via email to

[Prev in Thread] Current Thread [Next in Thread]