scsi-disk: Add device_id property
The new device_id property specifies which value to use for the vendor specific designator in the Device Identification VPD page. In particular, this is necessary for libvirt to maintain guest ABI compatibility when no serial number is given and a VM is switched from -drive (where the BlockBackend name is used) to -blockdev (where the vendor specific designator is left out by default). Signed-off-by: Kevin Wolf <kwolf@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
a8f58afcdb
commit
7471a649fc
|
@ -104,6 +104,7 @@ typedef struct SCSIDiskState
|
||||||
char *serial;
|
char *serial;
|
||||||
char *vendor;
|
char *vendor;
|
||||||
char *product;
|
char *product;
|
||||||
|
char *device_id;
|
||||||
bool tray_open;
|
bool tray_open;
|
||||||
bool tray_locked;
|
bool tray_locked;
|
||||||
/*
|
/*
|
||||||
|
@ -642,13 +643,8 @@ static int scsi_disk_emulate_vpd_page(SCSIRequest *req, uint8_t *outbuf)
|
||||||
|
|
||||||
case 0x83: /* Device identification page, mandatory */
|
case 0x83: /* Device identification page, mandatory */
|
||||||
{
|
{
|
||||||
const char *str = s->serial ?: blk_name(s->qdev.conf.blk);
|
int id_len = s->device_id ? MIN(strlen(s->device_id), 255 - 8) : 0;
|
||||||
int max_len = s->serial ? 20 : 255 - 8;
|
|
||||||
int id_len = strlen(str);
|
|
||||||
|
|
||||||
if (id_len > max_len) {
|
|
||||||
id_len = max_len;
|
|
||||||
}
|
|
||||||
DPRINTF("Inquiry EVPD[Device identification] "
|
DPRINTF("Inquiry EVPD[Device identification] "
|
||||||
"buffer size %zd\n", req->cmd.xfer);
|
"buffer size %zd\n", req->cmd.xfer);
|
||||||
|
|
||||||
|
@ -657,7 +653,7 @@ static int scsi_disk_emulate_vpd_page(SCSIRequest *req, uint8_t *outbuf)
|
||||||
outbuf[buflen++] = 0; /* not officially assigned */
|
outbuf[buflen++] = 0; /* not officially assigned */
|
||||||
outbuf[buflen++] = 0; /* reserved */
|
outbuf[buflen++] = 0; /* reserved */
|
||||||
outbuf[buflen++] = id_len; /* length of data following */
|
outbuf[buflen++] = id_len; /* length of data following */
|
||||||
memcpy(outbuf + buflen, str, id_len);
|
memcpy(outbuf + buflen, s->device_id, id_len);
|
||||||
buflen += id_len;
|
buflen += id_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2363,6 +2359,16 @@ static void scsi_realize(SCSIDevice *dev, Error **errp)
|
||||||
if (!s->vendor) {
|
if (!s->vendor) {
|
||||||
s->vendor = g_strdup("QEMU");
|
s->vendor = g_strdup("QEMU");
|
||||||
}
|
}
|
||||||
|
if (!s->device_id) {
|
||||||
|
if (s->serial) {
|
||||||
|
s->device_id = g_strdup_printf("%.20s", s->serial);
|
||||||
|
} else {
|
||||||
|
const char *str = blk_name(s->qdev.conf.blk);
|
||||||
|
if (str && *str) {
|
||||||
|
s->device_id = g_strdup(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (blk_is_sg(s->qdev.conf.blk)) {
|
if (blk_is_sg(s->qdev.conf.blk)) {
|
||||||
error_setg(errp, "unwanted /dev/sg*");
|
error_setg(errp, "unwanted /dev/sg*");
|
||||||
|
@ -2921,7 +2927,9 @@ static const TypeInfo scsi_disk_base_info = {
|
||||||
DEFINE_PROP_STRING("ver", SCSIDiskState, version), \
|
DEFINE_PROP_STRING("ver", SCSIDiskState, version), \
|
||||||
DEFINE_PROP_STRING("serial", SCSIDiskState, serial), \
|
DEFINE_PROP_STRING("serial", SCSIDiskState, serial), \
|
||||||
DEFINE_PROP_STRING("vendor", SCSIDiskState, vendor), \
|
DEFINE_PROP_STRING("vendor", SCSIDiskState, vendor), \
|
||||||
DEFINE_PROP_STRING("product", SCSIDiskState, product)
|
DEFINE_PROP_STRING("product", SCSIDiskState, product), \
|
||||||
|
DEFINE_PROP_STRING("device_id", SCSIDiskState, device_id)
|
||||||
|
|
||||||
|
|
||||||
static Property scsi_hd_properties[] = {
|
static Property scsi_hd_properties[] = {
|
||||||
DEFINE_SCSI_DISK_PROPERTIES(),
|
DEFINE_SCSI_DISK_PROPERTIES(),
|
||||||
|
|
Loading…
Reference in a new issue