-- john.cooper@xxxxxxxxxxxxxxxxxx
hw/virtio-blk.c | 15 ++++++++++++++- hw/virtio-blk.h | 3 +++ sysemu.h | 4 +++- 3 files changed, 20 insertions(+), 2 deletions(-) ================================================================= --- a/qemu/hw/virtio-blk.h +++ b/qemu/hw/virtio-blk.h @@ -28,6 +28,7 @@ #define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */ #define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */ #define VIRTIO_BLK_F_GEOMETRY 4 /* Indicates support of legacy geometry */ +#define VIRTIO_BLK_F_SN 7 /* serial number supported */ struct virtio_blk_config { @@ -37,6 +38,8 @@ struct virtio_blk_config uint16_t cylinders; uint8_t heads; uint8_t sectors; + uint32_t _blk_size; /* structure pad, currently unused */ + uint8_t serial[BLOCK_SERIAL_STRLEN]; } __attribute__((packed)); /* These two define direction. */ ================================================================= --- a/qemu/hw/virtio-blk.c +++ b/qemu/hw/virtio-blk.c @@ -22,6 +22,7 @@ typedef struct VirtIOBlock BlockDriverState *bs; VirtQueue *vq; void *rq; + char serial_str[BLOCK_SERIAL_STRLEN + 1]; } VirtIOBlock; static VirtIOBlock *to_virtio_blk(VirtIODevice *vdev) @@ -238,6 +239,8 @@ static void virtio_blk_reset(VirtIODevic qemu_aio_flush(); } +/* coalesce internal state, copy to pci i/o region 0 + */ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config) { VirtIOBlock *s = to_virtio_blk(vdev); @@ -252,12 +255,17 @@ static void virtio_blk_update_config(Vir stw_raw(&blkcfg.cylinders, cylinders); blkcfg.heads = heads; blkcfg.sectors = secs; + memcpy(&blkcfg.serial, s->serial_str, sizeof (blkcfg.serial)); memcpy(config, &blkcfg, sizeof(blkcfg)); } static uint32_t virtio_blk_get_features(VirtIODevice *vdev) { - return (1 << VIRTIO_BLK_F_SEG_MAX | 1 << VIRTIO_BLK_F_GEOMETRY); + VirtIOBlock *s = to_virtio_blk(vdev); + char ser_set = strcmp(s->serial_str, "0"); + + return (1 << VIRTIO_BLK_F_SEG_MAX | 1 << VIRTIO_BLK_F_GEOMETRY | + (ser_set ? 1 << VIRTIO_BLK_F_SN : 0)); } static void virtio_blk_save(QEMUFile *f, void *opaque) @@ -298,6 +306,7 @@ void *virtio_blk_init(PCIBus *bus, Block VirtIOBlock *s; int cylinders, heads, secs; static int virtio_blk_id; + char *ps = drive_get_serial(bs); s = (VirtIOBlock *)virtio_init_pci(bus, "virtio-blk", PCI_VENDOR_ID_REDHAT_QUMRANET, @@ -314,6 +323,10 @@ void *virtio_blk_init(PCIBus *bus, Block s->vdev.reset = virtio_blk_reset; s->bs = bs; s->rq = NULL; + if (strlen(ps)) + strncpy(s->serial_str, ps, sizeof (s->serial_str)); + else + snprintf(s->serial_str, sizeof (s->serial_str), "0"); bs->devfn = s->vdev.pci_dev.devfn; bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs); bdrv_set_geometry_hint(s->bs, cylinders, heads, secs); ================================================================= --- a/qemu/sysemu.h +++ b/qemu/sysemu.h @@ -133,13 +133,15 @@ typedef enum { BLOCK_ERR_STOP_ANY } BlockInterfaceErrorAction; +#define BLOCK_SERIAL_STRLEN 20 + typedef struct DriveInfo { BlockDriverState *bdrv; BlockInterfaceType type; int bus; int unit; BlockInterfaceErrorAction onerror; - char serial[21]; + char serial[BLOCK_SERIAL_STRLEN + 1]; int used; int drive_opt_idx; } DriveInfo;