=== KERNEL ===
@@ -351,8 +351,14 @@ static int __devinit virtblk_probe(struct
virtio_device *vdev)
/* No need to bounce any requests */
blk_queue_bounce_limit(vblk->disk->queue, BLK_BOUNCE_ANY);
- /* No real sector limit. */
- blk_queue_max_sectors(vblk->disk->queue, -1U);
+ /* Host can optionally specify maximum sector size for I/Os. */
+ err = virtio_config_val(vdev, VIRTIO_BLK_F_SECTOR_MAX,
+ offsetof(struct virtio_blk_config, sectors_max),
+ &v);
+ if (!err)
+ blk_queue_max_sectors(vblk->disk->queue, v);
+ else
+ blk_queue_max_sectors(vblk->disk->queue, -1U);
/* Host can optionally specify maximum segment size and number of
* segments. */
@@ -412,7 +418,7 @@ static struct virtio_device_id id_table[] = {
static unsigned int features[] = {
VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
- VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_FLUSH
+ VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_SECTOR_MAX
};
/*
@@ -15,6 +15,7 @@
#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/
#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */
#define VIRTIO_BLK_F_FLUSH 9 /* Cache flush command support */
+#define VIRTIO_BLK_F_SECTOR_MAX 10 /* Maximum # of sectors per I/O */
struct virtio_blk_config {
/* The capacity (in 512-byte sectors). */
@@ -29,6 +30,7 @@ struct virtio_blk_config {
__u8 heads;
__u8 sectors;
} geometry;
+ __u32 sectors_max;
/* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
__u32 blk_size;
} __attribute__((packed));
=== USER-SPACE ===
@@ -800,6 +800,26 @@ int64_t bdrv_getlength(BlockDriverState *bs)
return drv->bdrv_getlength(bs);
}
+/**
+ * Maximum length of an I/O in sectors. Return -1 if not specified.
+ */
+void bdrv_get_max_sectors(BlockDriverState *bs, uint32_t *sectors_max)
+{
+ BlockDriver *drv = bs->drv;
+ if ((!drv) || (!drv->bdrv_get_max_sectors))
+ *sectors_max = -1;
+ else
+ * sectors_max = drv->bdrv_get_max_sectors(bs);
+}
+
+int bdrv_uses_max_sectors(BlockDriverState *bs)
+{
+ BlockDriver *drv = bs->drv;
+ if ((!drv) || (!drv->bdrv_get_max_sectors))
+ return 0;
+ return 1;
+}
+
/* return 0 as number of sectors if no device present or error */
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr)
{
@@ -72,6 +72,8 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
const void *buf, int count);
int bdrv_truncate(BlockDriverState *bs, int64_t offset);
int64_t bdrv_getlength(BlockDriverState *bs);
+void bdrv_get_max_sectors(BlockDriverState *bs, uint32_t *sectors_max);
+int bdrv_uses_max_sectors(BlockDriverState *bs);
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads,
int *psecs);
int bdrv_commit(BlockDriverState *bs);
@@ -81,6 +81,7 @@ struct BlockDriver {
const char *protocol_name;
int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
int64_t (*bdrv_getlength)(BlockDriverState *bs);
+ uint32_t (*bdrv_get_max_sectors)(BlockDriverState *bs);
int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
@@ -413,13 +413,16 @@ static void virtio_blk_update_config(VirtIODevice
*vdev, uint8_t *config)
struct virtio_blk_config blkcfg;
uint64_t capacity;
int cylinders, heads, secs;
+ uint32_t sectors_max;
bdrv_get_geometry(s->bs, &capacity);
bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);
+ bdrv_get_max_sectors(s->bs, §ors_max);
memset(&blkcfg, 0, sizeof(blkcfg));
stq_raw(&blkcfg.capacity, capacity);
stl_raw(&blkcfg.seg_max, 128 - 2);
stw_raw(&blkcfg.cylinders, cylinders);
+ stl_raw(&blkcfg.sectors_max, sectors_max);
blkcfg.heads = heads;
blkcfg.sectors = secs;
blkcfg.size_max = 0;
@@ -448,6 +451,9 @@ static uint32_t virtio_blk_get_features(VirtIODevice
*vdev)
if (bdrv_is_read_only(s->bs))
features |= 1 << VIRTIO_BLK_F_RO;
+ if (bdrv_uses_max_sectors(s->bs))
+ features |= 1 << VIRTIO_BLK_F_SECTOR_MAX;
+
return features;
}
@@ -32,6 +32,7 @@
#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru
*/
#define VIRTIO_BLK_F_IDENTIFY 8 /* ATA IDENTIFY supported */
#define VIRTIO_BLK_F_WCACHE 9 /* write cache enabled */
+#define VIRTIO_BLK_F_SECTOR_MAX 10 /* Maximum # of sectors per I/O */
#define VIRTIO_BLK_ID_LEN 256 /* length of identify u16 array */