[libvirt] [PATCH RFC 0/5] add support for scsi-generic for virtio-scsi

This patch series tried to implement the fifth part of Paolo's proposal: http://permalink.gmane.org/gmane.comp.emulators.libvirt/50428 It is not completed. But it may for use. Needs some more works on: src/qemu/qemu_hostdev.c src/qemu/qemu_hotplug.c We may also need create src/util/virscsi.[hc] like src/util/vir(pci|usb).[hc], add sg* to nodedev tree and some others. As scsi hostdev needs -drive and -device like disk. There are two approaches: a) build a disk then use the disk related functions, b) create new function for it. I chose the last one as it is clearer and easier. But this may create some redundant codes. Any ideas? Han Cheng (5): conf: Introduce readonly to hostdev and change helper function conf: Introduce scsi hostdev qemu: New cap flag for scsi-generic qemu: Build qemu command line for scsi-generic tests: tests for scsi hostdev docs/formatdomain.html.in | 36 +- docs/schemas/domaincommon.rng | 38 ++ src/conf/domain_audit.c | 10 src/conf/domain_conf.c | 167 +++++++++- src/conf/domain_conf.h | 13 src/libvirt_private.syms | 2 src/qemu/qemu_capabilities.c | 15 src/qemu/qemu_capabilities.h | 2 src/qemu/qemu_command.c | 160 +++++++++ tests/qemuhelpdata/qemu-1.0-device | 10 tests/qemuhelpdata/qemu-1.1.0-device | 10 tests/qemuhelpdata/qemu-1.2.0-device | 5 tests/qemuhelpdata/qemu-kvm-1.2.0-device | 5 tests/qemuhelptest.c | 19 - tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.args | 9 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.xml | 34 ++ tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.args | 9 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.xml | 35 ++ tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.args | 9 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.xml | 34 ++ tests/qemuxml2argvtest.c | 12 tests/qemuxml2xmltest.c | 4 22 files changed, 607 insertions(+), 31 deletions(-)

The only parameter in -drive affect scsi-generic is readonly. Introduce <readonly/> to <hostdev>. The helper function to look up disk controller model may be used by scsi hostdev. But it should be changed to use info. --- docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_conf.c | 18 ++++++++++++++---- src/conf/domain_conf.h | 6 ++++-- src/libvirt_private.syms | 2 +- src/qemu/qemu_command.c | 4 ++-- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index e7231cc..fbb4001 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2898,6 +2898,11 @@ <ref name="alias"/> </optional> <optional> + <element name='readonly'> + <empty/> + </element> + </optional> + <optional> <ref name="deviceBoot"/> </optional> <optional> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 995cf0c..5e385e4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -78,6 +78,7 @@ typedef enum { VIR_DOMAIN_XML_INTERNAL_PCI_ORIG_STATES = (1<<18), VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM = (1<<19), VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT = (1<<20), + VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY = (1<<21), } virDomainXMLInternalFlags; VIR_ENUM_IMPL(virDomainTaint, VIR_DOMAIN_TAINT_LAST, @@ -2173,6 +2174,8 @@ virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info, unsigned int flags) return true; if (info->bootIndex) return true; + if (info->readonly) + return true; return false; } @@ -2395,6 +2398,8 @@ virDomainDeviceInfoFormat(virBufferPtr buf, virDomainDeviceInfoPtr info, unsigned int flags) { + if ((flags & VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY) && info->readonly) + virBufferAsprintf(buf, " <readonly/>\n"); if ((flags & VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT) && info->bootIndex) virBufferAsprintf(buf, " <boot order='%d'/>\n", info->bootIndex); @@ -2803,6 +2808,10 @@ virDomainDeviceInfoParseXML(xmlNodePtr node, (flags & VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM) && xmlStrEqual(cur->name, BAD_CAST "rom")) { rom = cur; + } else if (info->readonly == 0 && + (flags & VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY) && + xmlStrEqual(cur->name, BAD_CAST "readonly")) { + info->readonly = 1; } } cur = cur->next; @@ -3291,8 +3300,8 @@ error: } int -virDomainDiskFindControllerModel(virDomainDefPtr def, - virDomainDiskDefPtr disk, +virDomainInfoFindControllerModel(virDomainDefPtr def, + virDomainDeviceInfoPtr info, int controllerType) { int model = -1; @@ -3300,7 +3309,7 @@ virDomainDiskFindControllerModel(virDomainDefPtr def, for (i = 0; i < def->ncontrollers; i++) { if (def->controllers[i]->type == controllerType && - def->controllers[i]->idx == disk->info.addr.drive.controller) + def->controllers[i]->idx == info->addr.drive.controller) model = def->controllers[i]->model; } @@ -7838,7 +7847,8 @@ virDomainHostdevDefParseXML(const xmlNodePtr node, if (def->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { if (virDomainDeviceInfoParseXML(node, bootMap, def->info, flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT - | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM) < 0) + | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM + | VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY) < 0) goto error; } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 5828ae2..39c5849 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -286,6 +286,8 @@ struct _virDomainDeviceInfo { /* bootIndex is only used for disk, network interface, hostdev * and redirdev devices */ int bootIndex; + /* readonly is only used for scsi hostdev */ + int readonly; }; enum virDomainSeclabelType { @@ -1951,8 +1953,8 @@ void virDomainInputDefFree(virDomainInputDefPtr def); void virDomainDiskDefFree(virDomainDiskDefPtr def); void virDomainLeaseDefFree(virDomainLeaseDefPtr def); void virDomainDiskHostDefFree(virDomainDiskHostDefPtr def); -int virDomainDiskFindControllerModel(virDomainDefPtr def, - virDomainDiskDefPtr disk, +int virDomainInfoFindControllerModel(virDomainDefPtr def, + virDomainDeviceInfoPtr info, int controllerType); virDomainDiskDefPtr virDomainDiskFindByBusAndDst(virDomainDefPtr def, int bus, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c7bd847..4fc6b32 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -143,7 +143,6 @@ virDomainDiskDeviceTypeToString; virDomainDiskErrorPolicyTypeFromString; virDomainDiskErrorPolicyTypeToString; virDomainDiskFindByBusAndDst; -virDomainDiskFindControllerModel; virDomainDiskGeometryTransTypeFromString; virDomainDiskGeometryTransTypeToString; virDomainDiskHostDefFree; @@ -213,6 +212,7 @@ virDomainHubTypeFromString; virDomainHubTypeToString; virDomainHypervTypeFromString; virDomainHypervTypeToString; +virDomainInfoFindControllerModel; virDomainInputDefFree; virDomainIoEventFdTypeFromString; virDomainIoEventFdTypeToString; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 201fac1..5eb9999 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -549,7 +549,7 @@ qemuAssignDeviceDiskAliasCustom(virDomainDefPtr def, if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) { if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) { controllerModel = - virDomainDiskFindControllerModel(def, disk, + virDomainInfoFindControllerModel(def, &disk->info, VIR_DOMAIN_CONTROLLER_TYPE_SCSI); if ((qemuSetScsiControllerModel(def, qemuCaps, &controllerModel)) < 0) @@ -2699,7 +2699,7 @@ qemuBuildDriveDevStr(virDomainDefPtr def, } controllerModel = - virDomainDiskFindControllerModel(def, disk, + virDomainInfoFindControllerModel(def, &disk->info, VIR_DOMAIN_CONTROLLER_TYPE_SCSI); if ((qemuSetScsiControllerModel(def, qemuCaps, &controllerModel)) < 0) goto error; -- 1.7.1

On 2013年03月04日 14:01, Han Cheng wrote:
The only parameter in -drive affect scsi-generic is readonly. Introduce <readonly/> to<hostdev>. The helper function to look up disk controller model may be used by scsi hostdev. But it should be changed to use info. --- docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_conf.c | 18 ++++++++++++++---- src/conf/domain_conf.h | 6 ++++-- src/libvirt_private.syms | 2 +- src/qemu/qemu_command.c | 4 ++-- 5 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index e7231cc..fbb4001 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2898,6 +2898,11 @@ <ref name="alias"/> </optional> <optional> +<element name='readonly'> +<empty/> +</element> +</optional> +<optional> <ref name="deviceBoot"/> </optional> <optional> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 995cf0c..5e385e4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -78,6 +78,7 @@ typedef enum { VIR_DOMAIN_XML_INTERNAL_PCI_ORIG_STATES = (1<<18), VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM = (1<<19), VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT = (1<<20), + VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY = (1<<21),
I think the "readonly" tag for hostdev can just always be exposed, as don't see any special reason to keep it internally.
} virDomainXMLInternalFlags;
VIR_ENUM_IMPL(virDomainTaint, VIR_DOMAIN_TAINT_LAST, @@ -2173,6 +2174,8 @@ virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info, unsigned int flags) return true; if (info->bootIndex) return true; + if (info->readonly) + return true;
And why it's of DeviceInfo struct?
return false; }
@@ -2395,6 +2398,8 @@ virDomainDeviceInfoFormat(virBufferPtr buf, virDomainDeviceInfoPtr info, unsigned int flags) { + if ((flags& VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY)&& info->readonly) + virBufferAsprintf(buf, "<readonly/>\n"); if ((flags& VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT)&& info->bootIndex) virBufferAsprintf(buf, "<boot order='%d'/>\n", info->bootIndex);
@@ -2803,6 +2808,10 @@ virDomainDeviceInfoParseXML(xmlNodePtr node, (flags& VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM)&& xmlStrEqual(cur->name, BAD_CAST "rom")) { rom = cur; + } else if (info->readonly == 0&& + (flags& VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY)&& + xmlStrEqual(cur->name, BAD_CAST "readonly")) { + info->readonly = 1; } } cur = cur->next; @@ -3291,8 +3300,8 @@ error: }
int -virDomainDiskFindControllerModel(virDomainDefPtr def, - virDomainDiskDefPtr disk, +virDomainInfoFindControllerModel(virDomainDefPtr def,
Not a good name. How about changing into: virDomainDeviceFindControllerModel.
+ virDomainDeviceInfoPtr info, int controllerType) { int model = -1; @@ -3300,7 +3309,7 @@ virDomainDiskFindControllerModel(virDomainDefPtr def,
for (i = 0; i< def->ncontrollers; i++) { if (def->controllers[i]->type == controllerType&& - def->controllers[i]->idx == disk->info.addr.drive.controller) + def->controllers[i]->idx == info->addr.drive.controller) model = def->controllers[i]->model; }
@@ -7838,7 +7847,8 @@ virDomainHostdevDefParseXML(const xmlNodePtr node, if (def->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { if (virDomainDeviceInfoParseXML(node, bootMap, def->info, flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT - | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM)< 0) + | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM + | VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY)< 0) goto error; }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 5828ae2..39c5849 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -286,6 +286,8 @@ struct _virDomainDeviceInfo { /* bootIndex is only used for disk, network interface, hostdev * and redirdev devices */ int bootIndex; + /* readonly is only used for scsi hostdev */ + int readonly;
This should be a member of virDomainHostdevDef instead.
};
enum virDomainSeclabelType { @@ -1951,8 +1953,8 @@ void virDomainInputDefFree(virDomainInputDefPtr def); void virDomainDiskDefFree(virDomainDiskDefPtr def); void virDomainLeaseDefFree(virDomainLeaseDefPtr def); void virDomainDiskHostDefFree(virDomainDiskHostDefPtr def); -int virDomainDiskFindControllerModel(virDomainDefPtr def, - virDomainDiskDefPtr disk, +int virDomainInfoFindControllerModel(virDomainDefPtr def, + virDomainDeviceInfoPtr info, int controllerType); virDomainDiskDefPtr virDomainDiskFindByBusAndDst(virDomainDefPtr def, int bus, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c7bd847..4fc6b32 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -143,7 +143,6 @@ virDomainDiskDeviceTypeToString; virDomainDiskErrorPolicyTypeFromString; virDomainDiskErrorPolicyTypeToString; virDomainDiskFindByBusAndDst; -virDomainDiskFindControllerModel; virDomainDiskGeometryTransTypeFromString; virDomainDiskGeometryTransTypeToString; virDomainDiskHostDefFree; @@ -213,6 +212,7 @@ virDomainHubTypeFromString; virDomainHubTypeToString; virDomainHypervTypeFromString; virDomainHypervTypeToString; +virDomainInfoFindControllerModel; virDomainInputDefFree; virDomainIoEventFdTypeFromString; virDomainIoEventFdTypeToString; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 201fac1..5eb9999 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -549,7 +549,7 @@ qemuAssignDeviceDiskAliasCustom(virDomainDefPtr def, if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) { if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) { controllerModel = - virDomainDiskFindControllerModel(def, disk, + virDomainInfoFindControllerModel(def,&disk->info, VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
if ((qemuSetScsiControllerModel(def, qemuCaps,&controllerModel))< 0) @@ -2699,7 +2699,7 @@ qemuBuildDriveDevStr(virDomainDefPtr def, }
controllerModel = - virDomainDiskFindControllerModel(def, disk, + virDomainInfoFindControllerModel(def,&disk->info, VIR_DOMAIN_CONTROLLER_TYPE_SCSI); if ((qemuSetScsiControllerModel(def, qemuCaps,&controllerModel))< 0) goto error;
You need new tests for the new XML.

Thanks for your comments~ Please correct me if I'm wrong. As I know, <source> in <hostdev> is parsed by virDomainHostdevSubsys(Pci/Usb)DefParseXML. Everything else in <hostdev> is parsed by virDomainDeviceInfoParseXML. I add readonly follow this. And this XML is tested by hostdev-scsi-readonly(named by your advice). Other problems will be fixed by next version. On 03/06/2013 01:40 PM, Osier Yang wrote:
On 2013年03月04日 14:01, Han Cheng wrote:
The only parameter in -drive affect scsi-generic is readonly. Introduce <readonly/> to<hostdev>. The helper function to look up disk controller model may be used by scsi hostdev. But it should be changed to use info. --- docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_conf.c | 18 ++++++++++++++---- src/conf/domain_conf.h | 6 ++++-- src/libvirt_private.syms | 2 +- src/qemu/qemu_command.c | 4 ++-- 5 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index e7231cc..fbb4001 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2898,6 +2898,11 @@ <ref name="alias"/> </optional> <optional> +<element name='readonly'> +<empty/> +</element> +</optional> +<optional> <ref name="deviceBoot"/> </optional> <optional> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 995cf0c..5e385e4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -78,6 +78,7 @@ typedef enum { VIR_DOMAIN_XML_INTERNAL_PCI_ORIG_STATES = (1<<18), VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM = (1<<19), VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT = (1<<20), + VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY = (1<<21),
I think the "readonly" tag for hostdev can just always be exposed, as don't see any special reason to keep it internally.
} virDomainXMLInternalFlags;
VIR_ENUM_IMPL(virDomainTaint, VIR_DOMAIN_TAINT_LAST, @@ -2173,6 +2174,8 @@ virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info, unsigned int flags) return true; if (info->bootIndex) return true; + if (info->readonly) + return true;
And why it's of DeviceInfo struct?
return false; }
@@ -2395,6 +2398,8 @@ virDomainDeviceInfoFormat(virBufferPtr buf, virDomainDeviceInfoPtr info, unsigned int flags) { + if ((flags& VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY)&& info->readonly) + virBufferAsprintf(buf, "<readonly/>\n"); if ((flags& VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT)&& info->bootIndex) virBufferAsprintf(buf, "<boot order='%d'/>\n", info->bootIndex);
@@ -2803,6 +2808,10 @@ virDomainDeviceInfoParseXML(xmlNodePtr node, (flags& VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM)&& xmlStrEqual(cur->name, BAD_CAST "rom")) { rom = cur; + } else if (info->readonly == 0&& + (flags& VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY)&& + xmlStrEqual(cur->name, BAD_CAST "readonly")) { + info->readonly = 1; } } cur = cur->next; @@ -3291,8 +3300,8 @@ error: }
int -virDomainDiskFindControllerModel(virDomainDefPtr def, - virDomainDiskDefPtr disk, +virDomainInfoFindControllerModel(virDomainDefPtr def,
Not a good name. How about changing into:
virDomainDeviceFindControllerModel.
+ virDomainDeviceInfoPtr info, int controllerType) { int model = -1; @@ -3300,7 +3309,7 @@ virDomainDiskFindControllerModel(virDomainDefPtr def,
for (i = 0; i< def->ncontrollers; i++) { if (def->controllers[i]->type == controllerType&& - def->controllers[i]->idx == disk->info.addr.drive.controller) + def->controllers[i]->idx == info->addr.drive.controller) model = def->controllers[i]->model; }
@@ -7838,7 +7847,8 @@ virDomainHostdevDefParseXML(const xmlNodePtr node, if (def->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { if (virDomainDeviceInfoParseXML(node, bootMap, def->info, flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT - | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM)< 0) + | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM + | VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY)< 0) goto error; }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 5828ae2..39c5849 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -286,6 +286,8 @@ struct _virDomainDeviceInfo { /* bootIndex is only used for disk, network interface, hostdev * and redirdev devices */ int bootIndex; + /* readonly is only used for scsi hostdev */ + int readonly;
This should be a member of virDomainHostdevDef instead.
};
enum virDomainSeclabelType { @@ -1951,8 +1953,8 @@ void virDomainInputDefFree(virDomainInputDefPtr def); void virDomainDiskDefFree(virDomainDiskDefPtr def); void virDomainLeaseDefFree(virDomainLeaseDefPtr def); void virDomainDiskHostDefFree(virDomainDiskHostDefPtr def); -int virDomainDiskFindControllerModel(virDomainDefPtr def, - virDomainDiskDefPtr disk, +int virDomainInfoFindControllerModel(virDomainDefPtr def, + virDomainDeviceInfoPtr info, int controllerType); virDomainDiskDefPtr virDomainDiskFindByBusAndDst(virDomainDefPtr def, int bus, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c7bd847..4fc6b32 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -143,7 +143,6 @@ virDomainDiskDeviceTypeToString; virDomainDiskErrorPolicyTypeFromString; virDomainDiskErrorPolicyTypeToString; virDomainDiskFindByBusAndDst; -virDomainDiskFindControllerModel; virDomainDiskGeometryTransTypeFromString; virDomainDiskGeometryTransTypeToString; virDomainDiskHostDefFree; @@ -213,6 +212,7 @@ virDomainHubTypeFromString; virDomainHubTypeToString; virDomainHypervTypeFromString; virDomainHypervTypeToString; +virDomainInfoFindControllerModel; virDomainInputDefFree; virDomainIoEventFdTypeFromString; virDomainIoEventFdTypeToString; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 201fac1..5eb9999 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -549,7 +549,7 @@ qemuAssignDeviceDiskAliasCustom(virDomainDefPtr def, if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) { if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) { controllerModel = - virDomainDiskFindControllerModel(def, disk, + virDomainInfoFindControllerModel(def,&disk->info, VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
if ((qemuSetScsiControllerModel(def, qemuCaps,&controllerModel))< 0) @@ -2699,7 +2699,7 @@ qemuBuildDriveDevStr(virDomainDefPtr def, }
controllerModel = - virDomainDiskFindControllerModel(def, disk, + virDomainInfoFindControllerModel(def,&disk->info, VIR_DOMAIN_CONTROLLER_TYPE_SCSI); if ((qemuSetScsiControllerModel(def, qemuCaps,&controllerModel))< 0) goto error;
You need new tests for the new XML.

On 2013年03月06日 20:38, Han Cheng wrote:
Thanks for your comments~ Please correct me if I'm wrong.
As I know,<source> in<hostdev> is parsed by virDomainHostdevSubsys(Pci/Usb)DefParseXML. Everything else in<hostdev> is parsed by virDomainDeviceInfoParseXML. I add readonly follow this.
I do think the new "readonly" member should be inside virDomainHostdevDef instead. On one hand, not all devices that has virDomainDeviceInfo want to support "readonly". On the other hand, see what virDomainDiskDef and virDomainFSDef does. if you add it in virDomainDeviceInfo, for disk, fs, (etc) devices, they are just duplicate. And what I mean for "exposing the readonly" is to make it external, but not internal instead, I.E. when you dump the XML, you should see it.
And this XML is tested by hostdev-scsi-readonly(named by your advice).
Other problems will be fixed by next version.
On 03/06/2013 01:40 PM, Osier Yang wrote:
On 2013年03月04日 14:01, Han Cheng wrote:
The only parameter in -drive affect scsi-generic is readonly. Introduce <readonly/> to<hostdev>. The helper function to look up disk controller model may be used by scsi hostdev. But it should be changed to use info. --- docs/schemas/domaincommon.rng | 5 +++++ src/conf/domain_conf.c | 18 ++++++++++++++---- src/conf/domain_conf.h | 6 ++++-- src/libvirt_private.syms | 2 +- src/qemu/qemu_command.c | 4 ++-- 5 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index e7231cc..fbb4001 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2898,6 +2898,11 @@ <ref name="alias"/> </optional> <optional> +<element name='readonly'> +<empty/> +</element> +</optional> +<optional> <ref name="deviceBoot"/> </optional> <optional> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 995cf0c..5e385e4 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -78,6 +78,7 @@ typedef enum { VIR_DOMAIN_XML_INTERNAL_PCI_ORIG_STATES = (1<<18), VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM = (1<<19), VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT = (1<<20), + VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY = (1<<21),
I think the "readonly" tag for hostdev can just always be exposed, as don't see any special reason to keep it internally.
} virDomainXMLInternalFlags;
VIR_ENUM_IMPL(virDomainTaint, VIR_DOMAIN_TAINT_LAST, @@ -2173,6 +2174,8 @@ virDomainDeviceInfoIsSet(virDomainDeviceInfoPtr info, unsigned int flags) return true; if (info->bootIndex) return true; + if (info->readonly) + return true;
And why it's of DeviceInfo struct?
return false; }
@@ -2395,6 +2398,8 @@ virDomainDeviceInfoFormat(virBufferPtr buf, virDomainDeviceInfoPtr info, unsigned int flags) { + if ((flags& VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY)&& info->readonly) + virBufferAsprintf(buf, "<readonly/>\n"); if ((flags& VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT)&& info->bootIndex) virBufferAsprintf(buf, "<boot order='%d'/>\n", info->bootIndex);
@@ -2803,6 +2808,10 @@ virDomainDeviceInfoParseXML(xmlNodePtr node, (flags& VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM)&& xmlStrEqual(cur->name, BAD_CAST "rom")) { rom = cur; + } else if (info->readonly == 0&& + (flags& VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY)&& + xmlStrEqual(cur->name, BAD_CAST "readonly")) { + info->readonly = 1; } } cur = cur->next; @@ -3291,8 +3300,8 @@ error: }
int -virDomainDiskFindControllerModel(virDomainDefPtr def, - virDomainDiskDefPtr disk, +virDomainInfoFindControllerModel(virDomainDefPtr def,
Not a good name. How about changing into:
virDomainDeviceFindControllerModel.
+ virDomainDeviceInfoPtr info, int controllerType) { int model = -1; @@ -3300,7 +3309,7 @@ virDomainDiskFindControllerModel(virDomainDefPtr def,
for (i = 0; i< def->ncontrollers; i++) { if (def->controllers[i]->type == controllerType&& - def->controllers[i]->idx == disk->info.addr.drive.controller) + def->controllers[i]->idx == info->addr.drive.controller) model = def->controllers[i]->model; }
@@ -7838,7 +7847,8 @@ virDomainHostdevDefParseXML(const xmlNodePtr node, if (def->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) { if (virDomainDeviceInfoParseXML(node, bootMap, def->info, flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT - | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM)< 0) + | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM + | VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY)< 0) goto error; }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 5828ae2..39c5849 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -286,6 +286,8 @@ struct _virDomainDeviceInfo { /* bootIndex is only used for disk, network interface, hostdev * and redirdev devices */ int bootIndex; + /* readonly is only used for scsi hostdev */ + int readonly;
This should be a member of virDomainHostdevDef instead.
};
enum virDomainSeclabelType { @@ -1951,8 +1953,8 @@ void virDomainInputDefFree(virDomainInputDefPtr def); void virDomainDiskDefFree(virDomainDiskDefPtr def); void virDomainLeaseDefFree(virDomainLeaseDefPtr def); void virDomainDiskHostDefFree(virDomainDiskHostDefPtr def); -int virDomainDiskFindControllerModel(virDomainDefPtr def, - virDomainDiskDefPtr disk, +int virDomainInfoFindControllerModel(virDomainDefPtr def, + virDomainDeviceInfoPtr info, int controllerType); virDomainDiskDefPtr virDomainDiskFindByBusAndDst(virDomainDefPtr def, int bus, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index c7bd847..4fc6b32 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -143,7 +143,6 @@ virDomainDiskDeviceTypeToString; virDomainDiskErrorPolicyTypeFromString; virDomainDiskErrorPolicyTypeToString; virDomainDiskFindByBusAndDst; -virDomainDiskFindControllerModel; virDomainDiskGeometryTransTypeFromString; virDomainDiskGeometryTransTypeToString; virDomainDiskHostDefFree; @@ -213,6 +212,7 @@ virDomainHubTypeFromString; virDomainHubTypeToString; virDomainHypervTypeFromString; virDomainHypervTypeToString; +virDomainInfoFindControllerModel; virDomainInputDefFree; virDomainIoEventFdTypeFromString; virDomainIoEventFdTypeToString; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 201fac1..5eb9999 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -549,7 +549,7 @@ qemuAssignDeviceDiskAliasCustom(virDomainDefPtr def, if (disk->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE) { if (disk->bus == VIR_DOMAIN_DISK_BUS_SCSI) { controllerModel = - virDomainDiskFindControllerModel(def, disk, + virDomainInfoFindControllerModel(def,&disk->info, VIR_DOMAIN_CONTROLLER_TYPE_SCSI);
if ((qemuSetScsiControllerModel(def, qemuCaps,&controllerModel))< 0) @@ -2699,7 +2699,7 @@ qemuBuildDriveDevStr(virDomainDefPtr def, }
controllerModel = - virDomainDiskFindControllerModel(def, disk, + virDomainInfoFindControllerModel(def,&disk->info, VIR_DOMAIN_CONTROLLER_TYPE_SCSI); if ((qemuSetScsiControllerModel(def, qemuCaps,&controllerModel))< 0) goto error;
You need new tests for the new XML.

Adding scsi hostdev, it should like: <hostdev mode='subsystem' type='scsi'> <source> <adapter name='scsi_host0'/> <address bus='0' target='0' unit='0'/> </source> <address type='drive' controller='0' bus='0' target='4' unit='8'/> </hostdev> --- docs/schemas/domaincommon.rng | 33 +++++++++ src/conf/domain_audit.c | 10 +++ src/conf/domain_conf.c | 149 +++++++++++++++++++++++++++++++++++++++-- src/conf/domain_conf.h | 7 ++ 4 files changed, 194 insertions(+), 5 deletions(-) diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index fbb4001..ebd0e42 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2931,6 +2931,7 @@ <choice> <ref name="hostdevsubsyspci"/> <ref name="hostdevsubsysusb"/> + <ref name="hostdevsubsysscsi"/> </choice> </define> @@ -2983,6 +2984,22 @@ </element> </define> + <define name="hostdevsubsysscsi"> + <attribute name="type"> + <value>scsi</value> + </attribute> + <element name="source"> + <element name="adapter"> + <attribute name="name"> + <ref name="scsiAdapter"/> + </attribute> + </element> + <element name="address"> + <ref name="scsiaddress"/> + </element> + </element> + </define> + <define name="hostdevcapsstorage"> <attribute name="type"> <value>storage</value> @@ -3027,6 +3044,17 @@ </attribute> </element> </define> + <define name="scsiaddress"> + <attribute name="bus"> + <ref name="driveBus"/> + </attribute> + <attribute name="target"> + <ref name="driveTarget"/> + </attribute> + <attribute name="unit"> + <ref name="driveUnit"/> + </attribute> + </define> <define name="usbportaddress"> <attribute name="bus"> <ref name="usbAddr"/> @@ -3893,4 +3921,9 @@ </element> <empty/> </define> + <define name="scsiAdapter"> + <data type="string"> + <param name="pattern">scsi_host[0-9]{1,2}</param> + </data> + </define> </grammar> diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c index c00bd11..e6d44b1 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -281,6 +281,16 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev, goto cleanup; } break; + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: + if (virAsprintf(&address, "%.3d:%.3d:%.3d:%.3d", + hostdev->source.subsys.u.scsi.adapter, + hostdev->source.subsys.u.scsi.bus, + hostdev->source.subsys.u.scsi.target, + hostdev->source.subsys.u.scsi.unit) < 0) { + VIR_WARN("OOM while encoding audit message"); + goto cleanup; + } + break; default: VIR_WARN("Unexpected hostdev type while encoding audit message: %d", hostdev->source.subsys.type); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 5e385e4..2be9129 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -557,7 +557,8 @@ VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST, VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST, "usb", - "pci") + "pci", + "scsi") VIR_ENUM_IMPL(virDomainHostdevCaps, VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST, "storage", @@ -2928,6 +2929,96 @@ virDomainParseLegacyDeviceAddress(char *devaddr, } static int +virDomainHostdevSubsysScsiDefParseXML(const xmlNodePtr node, + virDomainHostdevDefPtr def) +{ + int ret = -1; + xmlNodePtr cur; + + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + if (xmlStrEqual(cur->name, BAD_CAST "address")) { + char *bus, *target, *unit; + + bus=virXMLPropString(cur, "bus"); + if (bus) { + ret = virStrToLong_ui(bus, NULL, 0, + &def->source.subsys.u.scsi.bus); + VIR_FREE(bus); + if (ret < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse bus %s"), bus); + goto out; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("scsi address needs bus id")); + goto out; + } + target=virXMLPropString(cur, "target"); + if (target) { + ret = virStrToLong_ui(target, NULL, 0, + &def->source.subsys.u.scsi.target); + VIR_FREE(target); + if (ret < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse target %s"), target); + goto out; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("scsi address needs target id")); + goto out; + } + unit=virXMLPropString(cur, "unit"); + if (unit) { + ret = virStrToLong_ui(unit, NULL, 0, + &def->source.subsys.u.scsi.unit); + VIR_FREE(unit); + if (ret < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse unit %s"), unit); + goto out; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("scsi address needs unit id")); + goto out; + } + } else if (xmlStrEqual(cur->name, BAD_CAST "adapter")) { + char *adapter; + adapter = virXMLPropString(cur, "name"); + if (adapter && STRSKIP(adapter, "scsi_host")) { + ret = virStrToLong_ui(adapter + strlen("scsi_host"), NULL, 0, + &def->source.subsys.u.scsi.adapter); + VIR_FREE(adapter); + if (ret < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse adapter %s"), adapter); + goto out; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("scsi needs adapter")); + goto out; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown scsi source type '%s'"), + cur->name); + goto out; + } + } + cur = cur->next; + } + + ret = 0; +out: + return ret; +} + +static int virDomainHostdevSubsysUsbDefParseXML(const xmlNodePtr node, virDomainHostdevDefPtr def) { @@ -3222,6 +3313,10 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, if (virDomainHostdevSubsysUsbDefParseXML(sourcenode, def) < 0) goto error; break; + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: + if (virDomainHostdevSubsysScsiDefParseXML(sourcenode, def) < 0) + goto error; + break; default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("address type='%s' not supported in hostdev interfaces"), @@ -12146,6 +12241,30 @@ virDomainDefMaybeAddSmartcardController(virDomainDefPtr def) return 0; } +static int +virDomainDefMaybeAddHostdevSCSIcontroller(virDomainDefPtr def) +{ + /* Look for any hostdev scsi dev */ + int i; + int maxController = -1; + virDomainHostdevDefPtr hostdev; + + for (i = 0; i < def->nhostdevs; i++) { + hostdev = *(def->hostdevs + i); + if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && + hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI && + (int)hostdev->info->addr.drive.controller > maxController) { + maxController = hostdev->info->addr.drive.controller; + } + } + + for (i = 0; i <= maxController; i++) { + if (virDomainDefMaybeAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_SCSI, i) < 0) + return -1; + } + + return 0; +} /* * Based on the declared <address/> info for any devices, @@ -12182,6 +12301,9 @@ virDomainDefAddImplicitControllers(virDomainDefPtr def) if (virDomainDefMaybeAddSmartcardController(def) < 0) return -1; + if (virDomainDefMaybeAddHostdevSCSIcontroller(def) < 0) + return -1; + return 0; } @@ -12997,6 +13119,15 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, virBufferAdjustIndent(buf, 2); switch (def->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: + virBufferAsprintf(buf, "<adapter name='scsi_host%d'/>\n", + def->source.subsys.u.scsi.adapter); + virBufferAsprintf(buf, "<address %sbus='%d' target='%d' unit='%d'/>\n", + includeTypeInAddr ? "type='scsi' " : "", + def->source.subsys.u.scsi.bus, + def->source.subsys.u.scsi.target, + def->source.subsys.u.scsi.unit); + break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: if (def->source.subsys.u.usb.vendor) { virBufferAsprintf(buf, "<vendor id='0x%.4x'/>\n", @@ -14250,10 +14381,18 @@ virDomainHostdevDefFormat(virBufferPtr buf, } virBufferAdjustIndent(buf, -6); - if (virDomainDeviceInfoFormat(buf, def->info, - flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT - | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM) < 0) - return -1; + if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && + def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) { + if (virDomainDeviceInfoFormat(buf, def->info, + flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT + | VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY) < 0) + return -1; + } else { + if (virDomainDeviceInfoFormat(buf, def->info, + flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT + | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM) < 0) + return -1; + } virBufferAddLit(buf, " </hostdev>\n"); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 39c5849..c04cb23 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -366,6 +366,7 @@ enum virDomainHostdevMode { enum virDomainHostdevSubsysType { VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI, + VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST }; @@ -385,6 +386,12 @@ struct _virDomainHostdevSubsys { unsigned vendor; unsigned product; } usb; + struct { + unsigned adapter; + unsigned bus; + unsigned target; + unsigned unit; + } scsi; virDevicePCIAddress pci; /* host address */ } u; }; -- 1.7.1

On 2013年03月04日 14:01, Han Cheng wrote:
Adding scsi hostdev, it should like:
<hostdev mode='subsystem' type='scsi'> <source> <adapter name='scsi_host0'/> <address bus='0' target='0' unit='0'/> </source> <address type='drive' controller='0' bus='0' target='4' unit='8'/> </hostdev> --- docs/schemas/domaincommon.rng | 33 +++++++++ src/conf/domain_audit.c | 10 +++ src/conf/domain_conf.c | 149 +++++++++++++++++++++++++++++++++++++++-- src/conf/domain_conf.h | 7 ++ 4 files changed, 194 insertions(+), 5 deletions(-)
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index fbb4001..ebd0e42 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2931,6 +2931,7 @@ <choice> <ref name="hostdevsubsyspci"/> <ref name="hostdevsubsysusb"/> +<ref name="hostdevsubsysscsi"/> </choice> </define>
@@ -2983,6 +2984,22 @@ </element> </define>
+<define name="hostdevsubsysscsi"> +<attribute name="type"> +<value>scsi</value> +</attribute> +<element name="source"> +<element name="adapter"> +<attribute name="name"> +<ref name="scsiAdapter"/> +</attribute> +</element> +<element name="address"> +<ref name="scsiaddress"/> +</element> +</element> +</define> + <define name="hostdevcapsstorage"> <attribute name="type"> <value>storage</value> @@ -3027,6 +3044,17 @@ </attribute> </element> </define> +<define name="scsiaddress"> +<attribute name="bus"> +<ref name="driveBus"/> +</attribute> +<attribute name="target"> +<ref name="driveTarget"/> +</attribute> +<attribute name="unit"> +<ref name="driveUnit"/> +</attribute> +</define> <define name="usbportaddress"> <attribute name="bus"> <ref name="usbAddr"/> @@ -3893,4 +3921,9 @@ </element> <empty/> </define> +<define name="scsiAdapter"> +<data type="string"> +<param name="pattern">scsi_host[0-9]{1,2}</param>
No need to have a duplicate definition. It can reuse what storage pool uses.
+</data> +</define> </grammar> diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c index c00bd11..e6d44b1 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -281,6 +281,16 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev, goto cleanup; } break; + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: + if (virAsprintf(&address, "%.3d:%.3d:%.3d:%.3d", + hostdev->source.subsys.u.scsi.adapter, + hostdev->source.subsys.u.scsi.bus, + hostdev->source.subsys.u.scsi.target, + hostdev->source.subsys.u.scsi.unit)< 0) { + VIR_WARN("OOM while encoding audit message"); + goto cleanup; + } + break; default: VIR_WARN("Unexpected hostdev type while encoding audit message: %d", hostdev->source.subsys.type); diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 5e385e4..2be9129 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -557,7 +557,8 @@ VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST,
VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST, "usb", - "pci") + "pci", + "scsi")
VIR_ENUM_IMPL(virDomainHostdevCaps, VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST, "storage", @@ -2928,6 +2929,96 @@ virDomainParseLegacyDeviceAddress(char *devaddr, }
static int +virDomainHostdevSubsysScsiDefParseXML(const xmlNodePtr node, + virDomainHostdevDefPtr def) +{ + int ret = -1; + xmlNodePtr cur;
If you define those variables here: char *bus, *target, *unit;
+ + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + if (xmlStrEqual(cur->name, BAD_CAST "address")) { + char *bus, *target, *unit; + + bus=virXMLPropString(cur, "bus"); + if (bus) {
These codes can be simplified as: if ((bus = virXMLPropString(cur, "bus")) < 0) { virReportError(...); goto out; } if (virStrToLong_ui(bus, NULL, 0, &def->source.subsys.u.scsi.bus) < 0) { virReportError(...); goto out; } With freeing the strings in "out". [1]
+ ret = virStrToLong_ui(bus, NULL, 0, +&def->source.subsys.u.scsi.bus); + VIR_FREE(bus); + if (ret< 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse bus %s"), bus); + goto out; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("scsi address needs bus id"));
Generally we uses strings like in this case: "bus must be specified for scsi hostdev address"
+ goto out; + } + target=virXMLPropString(cur, "target"); + if (target) { + ret = virStrToLong_ui(target, NULL, 0, +&def->source.subsys.u.scsi.target); + VIR_FREE(target); + if (ret< 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse target %s"), target); + goto out; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("scsi address needs target id")); + goto out; + } + unit=virXMLPropString(cur, "unit"); + if (unit) { + ret = virStrToLong_ui(unit, NULL, 0, +&def->source.subsys.u.scsi.unit); + VIR_FREE(unit); + if (ret< 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse unit %s"), unit); + goto out; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("scsi address needs unit id")); + goto out; + } + } else if (xmlStrEqual(cur->name, BAD_CAST "adapter")) { + char *adapter; + adapter = virXMLPropString(cur, "name"); + if (adapter&& STRSKIP(adapter, "scsi_host")) { + ret = virStrToLong_ui(adapter + strlen("scsi_host"), NULL, 0, +&def->source.subsys.u.scsi.adapter);
Why not storing the adapter name as a string instead?
+ VIR_FREE(adapter); + if (ret< 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse adapter %s"), adapter); + goto out; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("scsi needs adapter")); + goto out; + } + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown scsi source type '%s'"), + cur->name); + goto out; + } + } + cur = cur->next; + } +
How about "adapter" is specified, but "source address" is not specified. Or the vice versa.
+ ret = 0; +out:
[1] VIR_FREE(bus); VIR_FREE(target); VIR_FREE(unit);
+ return ret; +} + +static int virDomainHostdevSubsysUsbDefParseXML(const xmlNodePtr node, virDomainHostdevDefPtr def) { @@ -3222,6 +3313,10 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node, if (virDomainHostdevSubsysUsbDefParseXML(sourcenode, def)< 0) goto error; break; + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: + if (virDomainHostdevSubsysScsiDefParseXML(sourcenode, def)< 0) + goto error; + break; default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("address type='%s' not supported in hostdev interfaces"), @@ -12146,6 +12241,30 @@ virDomainDefMaybeAddSmartcardController(virDomainDefPtr def) return 0; }
+static int +virDomainDefMaybeAddHostdevSCSIcontroller(virDomainDefPtr def) +{ + /* Look for any hostdev scsi dev */ + int i; + int maxController = -1; + virDomainHostdevDefPtr hostdev; + + for (i = 0; i< def->nhostdevs; i++) { + hostdev = *(def->hostdevs + i); + if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS&& + hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI&& + (int)hostdev->info->addr.drive.controller> maxController) { + maxController = hostdev->info->addr.drive.controller; + } + } + + for (i = 0; i<= maxController; i++) { + if (virDomainDefMaybeAddController(def, VIR_DOMAIN_CONTROLLER_TYPE_SCSI, i)< 0) + return -1; + } + + return 0; +}
/* * Based on the declared<address/> info for any devices, @@ -12182,6 +12301,9 @@ virDomainDefAddImplicitControllers(virDomainDefPtr def) if (virDomainDefMaybeAddSmartcardController(def)< 0) return -1;
+ if (virDomainDefMaybeAddHostdevSCSIcontroller(def)< 0) + return -1; + return 0; }
@@ -12997,6 +13119,15 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, virBufferAdjustIndent(buf, 2); switch (def->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: + virBufferAsprintf(buf, "<adapter name='scsi_host%d'/>\n",
This is hard code. Assuming that a scsi host device can have different name with "scsi_host" on platform other than Linux. So again, IMHO we should just storing the adapter name as string.
+ def->source.subsys.u.scsi.adapter); + virBufferAsprintf(buf, "<address %sbus='%d' target='%d' unit='%d'/>\n", + includeTypeInAddr ? "type='scsi' " : "", + def->source.subsys.u.scsi.bus, + def->source.subsys.u.scsi.target, + def->source.subsys.u.scsi.unit); + break; case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: if (def->source.subsys.u.usb.vendor) { virBufferAsprintf(buf, "<vendor id='0x%.4x'/>\n", @@ -14250,10 +14381,18 @@ virDomainHostdevDefFormat(virBufferPtr buf, } virBufferAdjustIndent(buf, -6);
- if (virDomainDeviceInfoFormat(buf, def->info, - flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT - | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM)< 0) - return -1; + if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS&& + def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) { + if (virDomainDeviceInfoFormat(buf, def->info, + flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT + | VIR_DOMAIN_XML_INTERNAL_ALLOW_READONLY)< 0)
As commented in 1/5. This is no need as long as you add the "readonly" as an external XML tag.
+ return -1; + } else { + if (virDomainDeviceInfoFormat(buf, def->info, + flags | VIR_DOMAIN_XML_INTERNAL_ALLOW_BOOT + | VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM)< 0) + return -1; + }
virBufferAddLit(buf, "</hostdev>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 39c5849..c04cb23 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -366,6 +366,7 @@ enum virDomainHostdevMode { enum virDomainHostdevSubsysType { VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI, + VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI,
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST }; @@ -385,6 +386,12 @@ struct _virDomainHostdevSubsys { unsigned vendor; unsigned product; } usb; + struct { + unsigned adapter;
char *adapter;
+ unsigned bus; + unsigned target; + unsigned unit; + } scsi; virDevicePCIAddress pci; /* host address */ } u; };

On 03/06/2013 02:24 PM, Osier Yang wrote:
On 2013年03月04日 14:01, Han Cheng wrote:
Adding scsi hostdev, it should like:
<hostdev mode='subsystem' type='scsi'> <source> <adapter name='scsi_host0'/> <address bus='0' target='0' unit='0'/> </source> <address type='drive' controller='0' bus='0' target='4' unit='8'/> </hostdev> @@ -3893,4 +3921,9 @@ </element> <empty/> </define> +<define name="scsiAdapter"> +<data type="string"> +<param name="pattern">scsi_host[0-9]{1,2}</param>
No need to have a duplicate definition. It can reuse what storage pool uses.
This is possible. But what make differences is the number. If we don't deal with it and storage it as string, we'll have to deal with it when build command line. Or, we just change the xml: <source> <adapter name='scsi_host0'/> <address bus='0' target='0' unit='0'/> </source> --> <source> <address host='0' bus='0' target='0' unit='0'/> </source> And actually 'host' can be 'controller'. Then it is drive address. We may reduce redundant codes.
@@ -12997,6 +13119,15 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, virBufferAdjustIndent(buf, 2); switch (def->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: + virBufferAsprintf(buf, "<adapter name='scsi_host%d'/>\n",
This is hard code. Assuming that a scsi host device can have different name with "scsi_host" on platform other than Linux. So again, IMHO we should just storing the adapter name as string.
Actually I'm quite uncomfortable when writing this hard code. If we change xml, this won't be problem.

Acutally, I've changed xml from Paolo's proposal. I deleted the <target> as it is not easy to parse for virDomainDeviceInfoParseXML and there is nothing else. And I changed address type from scsi to drive as they are the same. On 03/06/2013 09:09 PM, Han Cheng wrote:
On 03/06/2013 02:24 PM, Osier Yang wrote:
On 2013年03月04日 14:01, Han Cheng wrote:
Adding scsi hostdev, it should like:
<hostdev mode='subsystem' type='scsi'> <source> <adapter name='scsi_host0'/> <address bus='0' target='0' unit='0'/> </source> <address type='drive' controller='0' bus='0' target='4' unit='8'/> </hostdev> @@ -3893,4 +3921,9 @@ </element> <empty/> </define> +<define name="scsiAdapter"> +<data type="string"> +<param name="pattern">scsi_host[0-9]{1,2}</param>
No need to have a duplicate definition. It can reuse what storage pool uses.
This is possible. But what make differences is the number. If we don't deal with it and storage it as string, we'll have to deal with it when build command line.
Or, we just change the xml: <source> <adapter name='scsi_host0'/> <address bus='0' target='0' unit='0'/> </source> --> <source> <address host='0' bus='0' target='0' unit='0'/> </source>
And actually 'host' can be 'controller'. Then it is drive address. We may reduce redundant codes.
@@ -12997,6 +13119,15 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, virBufferAdjustIndent(buf, 2); switch (def->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: + virBufferAsprintf(buf, "<adapter name='scsi_host%d'/>\n",
This is hard code. Assuming that a scsi host device can have different name with "scsi_host" on platform other than Linux. So again, IMHO we should just storing the adapter name as string.
Actually I'm quite uncomfortable when writing this hard code. If we change xml, this won't be problem.
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list
-- -------------------------------------------------- Han Cheng Nanjing Fujitsu Nanda Software Tech. Co., Ltd.(FNST) No. 6 Wenzhu Road, Nanjing, 210012, China TEL: +86+25-86630566-8540 FUJITSU INTERNAL: 79955-8540 FAX: +86+25-83317685 MAIL: hanc.fnst@cn.fujitsu.com --------------------------------------------------

On 2013年03月06日 21:09, Han Cheng wrote:
On 03/06/2013 02:24 PM, Osier Yang wrote:
On 2013年03月04日 14:01, Han Cheng wrote:
Adding scsi hostdev, it should like:
<hostdev mode='subsystem' type='scsi'> <source> <adapter name='scsi_host0'/> <address bus='0' target='0' unit='0'/> </source> <address type='drive' controller='0' bus='0' target='4' unit='8'/> </hostdev> @@ -3893,4 +3921,9 @@ </element> <empty/> </define> +<define name="scsiAdapter"> +<data type="string"> +<param name="pattern">scsi_host[0-9]{1,2}</param>
No need to have a duplicate definition. It can reuse what storage pool uses.
I mean you can reuse the schema definition of storage pool.
This is possible. But what make differences is the number. If we don't deal with it and storage it as string, we'll have to deal with it when build command line.
Please do it when building command line. The XML should be generic for all drivers, not specificly for one driver.
Or, we just change the xml: <source> <adapter name='scsi_host0'/> <address bus='0' target='0' unit='0'/> </source> --> <source> <address host='0' bus='0' target='0' unit='0'/> </source>
And actually 'host' can be 'controller'. Then it is drive address. We may reduce redundant codes.
I'm not a fan of this idea. As we will want the adapter name like "scsi_host0" anyway when associating the scsi storage pool, especially the scsi pool behind a vHBA, which is represented by wwnn/wwpn, which is not possible to represented by a number. And on the other hand, reusing controller makes things confused.
@@ -12997,6 +13119,15 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf, virBufferAdjustIndent(buf, 2); switch (def->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: + virBufferAsprintf(buf, "<adapter name='scsi_host%d'/>\n",
This is hard code. Assuming that a scsi host device can have different name with "scsi_host" on platform other than Linux. So again, IMHO we should just storing the adapter name as string.
Actually I'm quite uncomfortable when writing this hard code. If we change xml, this won't be problem.

On 03/06/2013 02:24 PM, Osier Yang wrote:
On 2013年03月04日 14:01, Han Cheng wrote:
@@ -2928,6 +2929,96 @@ virDomainParseLegacyDeviceAddress(char *devaddr, }
static int +virDomainHostdevSubsysScsiDefParseXML(const xmlNodePtr node, + virDomainHostdevDefPtr def) +{ + int ret = -1; + xmlNodePtr cur;
If you define those variables here:
char *bus, *target, *unit;
+ + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + if (xmlStrEqual(cur->name, BAD_CAST "address")) { + char *bus, *target, *unit; + + bus=virXMLPropString(cur, "bus"); + if (bus) {
These codes can be simplified as:
if ((bus = virXMLPropString(cur, "bus"))< 0) { virReportError(...); goto out; }
if (virStrToLong_ui(bus, NULL, 0,&def->source.subsys.u.scsi.bus)< 0) { virReportError(...); goto out; }
With freeing the strings in "out". [1]
+ ret = virStrToLong_ui(bus, NULL, 0, +&def->source.subsys.u.scsi.bus); + VIR_FREE(bus); + if (ret< 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse bus %s"), bus); + goto out; ... + } + } + cur = cur->next; + } + + ret = 0; +out:
[1]
VIR_FREE(bus); VIR_FREE(target); VIR_FREE(unit);
+ return ret; +} + This may cause memory leak if someone add more than one <address> by mistake.
Regards, Cheng

On 2013年03月21日 17:01, Han Cheng wrote:
On 03/06/2013 02:24 PM, Osier Yang wrote:
On 2013年03月04日 14:01, Han Cheng wrote:
@@ -2928,6 +2929,96 @@ virDomainParseLegacyDeviceAddress(char *devaddr, }
static int +virDomainHostdevSubsysScsiDefParseXML(const xmlNodePtr node, + virDomainHostdevDefPtr def) +{ + int ret = -1; + xmlNodePtr cur;
If you define those variables here:
char *bus, *target, *unit;
+ + cur = node->children; + while (cur != NULL) { + if (cur->type == XML_ELEMENT_NODE) { + if (xmlStrEqual(cur->name, BAD_CAST "address")) { + char *bus, *target, *unit; + + bus=virXMLPropString(cur, "bus"); + if (bus) {
These codes can be simplified as:
if ((bus = virXMLPropString(cur, "bus"))< 0) { virReportError(...); goto out; }
if (virStrToLong_ui(bus, NULL, 0,&def->source.subsys.u.scsi.bus)< 0) { virReportError(...); goto out; }
With freeing the strings in "out". [1]
+ ret = virStrToLong_ui(bus, NULL, 0, +&def->source.subsys.u.scsi.bus); + VIR_FREE(bus); + if (ret< 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("cannot parse bus %s"), bus); + goto out; ... + } + } + cur = cur->next; + } + + ret = 0; +out:
[1]
VIR_FREE(bus); VIR_FREE(target); VIR_FREE(unit);
+ return ret; +} + This may cause memory leak if someone add more than one<address> by mistake.
No, as they are free'ed anyway after 1 round parsing (assuming there are multiple address specified indeed), regardless of whether the parsing succeeded or not. And the things we store in the memory for these attributes are numbers. So no memory leak. Osier

Adding two caps to support scsi-generic: QEMU_CAPS_SCSI_GENERIC QEMU_CAPS_SCSI_HOST_BOOTINDEX --- src/qemu/qemu_capabilities.c | 15 +++++++++++++-- src/qemu/qemu_capabilities.h | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 40022c1..01580d1 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -210,6 +210,9 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "rng-random", /* 130 */ "rng-egd", + "scsi-generic", + "scsi-generic.bootindex", + ); struct _virQEMUCaps { @@ -1331,11 +1334,12 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "VGA", QEMU_CAPS_DEVICE_VGA }, { "cirrus-vga", QEMU_CAPS_DEVICE_CIRRUS_VGA }, { "vmware-svga", QEMU_CAPS_DEVICE_VMWARE_SVGA }, - { "usb-serial", QEMU_CAPS_DEVICE_USB_SERIAL}, - { "usb-net", QEMU_CAPS_DEVICE_USB_NET}, + { "usb-serial", QEMU_CAPS_DEVICE_USB_SERIAL }, + { "usb-net", QEMU_CAPS_DEVICE_USB_NET }, { "virtio-rng-pci", QEMU_CAPS_DEVICE_VIRTIO_RNG }, { "rng-random", QEMU_CAPS_OBJECT_RNG_RANDOM }, { "rng-egd", QEMU_CAPS_OBJECT_RNG_EGD }, + { "scsi-generic", QEMU_CAPS_SCSI_GENERIC }, }; @@ -1382,6 +1386,10 @@ static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsUsbHost[] = { { "bootindex", QEMU_CAPS_USB_HOST_BOOTINDEX }, }; +static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsScsiHost[] = { + { "bootindex", QEMU_CAPS_SCSI_HOST_BOOTINDEX }, +}; + struct virQEMUCapsObjectTypeProps { const char *type; struct virQEMUCapsStringFlags *props; @@ -1411,6 +1419,8 @@ static struct virQEMUCapsObjectTypeProps virQEMUCapsObjectProps[] = { ARRAY_CARDINALITY(virQEMUCapsObjectPropsUsbRedir) }, { "usb-host", virQEMUCapsObjectPropsUsbHost, ARRAY_CARDINALITY(virQEMUCapsObjectPropsUsbHost) }, + { "scsi-generic", virQEMUCapsObjectPropsScsiHost, + ARRAY_CARDINALITY(virQEMUCapsObjectPropsScsiHost) }, }; @@ -1608,6 +1618,7 @@ virQEMUCapsExtractDeviceStr(const char *qemu, "-device", "usb-redir,?", "-device", "ide-drive,?", "-device", "usb-host,?", + "-device", "scsi-generic,?", NULL); /* qemu -help goes to stdout, but qemu -device ? goes to stderr. */ virCommandSetErrorBuffer(cmd, &output); diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index a895867..7d45e30 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -171,6 +171,8 @@ enum virQEMUCapsFlags { QEMU_CAPS_OBJECT_RNG_RANDOM = 130, /* the rng-random backend for virtio rng */ QEMU_CAPS_OBJECT_RNG_EGD = 131, /* EGD protocol daemon for rng */ + QEMU_CAPS_SCSI_GENERIC = 132, /* -device scsi-generic */ + QEMU_CAPS_SCSI_HOST_BOOTINDEX = 133, /* scsi-generic.bootindex */ QEMU_CAPS_LAST, /* this must always be the last item */ }; -- 1.7.1

On 2013年03月04日 14:01, Han Cheng wrote:
Adding two caps to support scsi-generic:
QEMU_CAPS_SCSI_GENERIC QEMU_CAPS_SCSI_HOST_BOOTINDEX --- src/qemu/qemu_capabilities.c | 15 +++++++++++++-- src/qemu/qemu_capabilities.h | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 40022c1..01580d1 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -210,6 +210,9 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
"rng-random", /* 130 */ "rng-egd", + "scsi-generic", + "scsi-generic.bootindex", + );
struct _virQEMUCaps { @@ -1331,11 +1334,12 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = { { "VGA", QEMU_CAPS_DEVICE_VGA }, { "cirrus-vga", QEMU_CAPS_DEVICE_CIRRUS_VGA }, { "vmware-svga", QEMU_CAPS_DEVICE_VMWARE_SVGA }, - { "usb-serial", QEMU_CAPS_DEVICE_USB_SERIAL}, - { "usb-net", QEMU_CAPS_DEVICE_USB_NET}, + { "usb-serial", QEMU_CAPS_DEVICE_USB_SERIAL }, + { "usb-net", QEMU_CAPS_DEVICE_USB_NET }, { "virtio-rng-pci", QEMU_CAPS_DEVICE_VIRTIO_RNG }, { "rng-random", QEMU_CAPS_OBJECT_RNG_RANDOM }, { "rng-egd", QEMU_CAPS_OBJECT_RNG_EGD }, + { "scsi-generic", QEMU_CAPS_SCSI_GENERIC }, };
@@ -1382,6 +1386,10 @@ static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsUsbHost[] = { { "bootindex", QEMU_CAPS_USB_HOST_BOOTINDEX }, };
+static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsScsiHost[] = { + { "bootindex", QEMU_CAPS_SCSI_HOST_BOOTINDEX }, +}; + struct virQEMUCapsObjectTypeProps { const char *type; struct virQEMUCapsStringFlags *props; @@ -1411,6 +1419,8 @@ static struct virQEMUCapsObjectTypeProps virQEMUCapsObjectProps[] = { ARRAY_CARDINALITY(virQEMUCapsObjectPropsUsbRedir) }, { "usb-host", virQEMUCapsObjectPropsUsbHost, ARRAY_CARDINALITY(virQEMUCapsObjectPropsUsbHost) }, + { "scsi-generic", virQEMUCapsObjectPropsScsiHost, + ARRAY_CARDINALITY(virQEMUCapsObjectPropsScsiHost) }, };
@@ -1608,6 +1618,7 @@ virQEMUCapsExtractDeviceStr(const char *qemu, "-device", "usb-redir,?", "-device", "ide-drive,?", "-device", "usb-host,?", + "-device", "scsi-generic,?", NULL); /* qemu -help goes to stdout, but qemu -device ? goes to stderr. */ virCommandSetErrorBuffer(cmd,&output); diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index a895867..7d45e30 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -171,6 +171,8 @@ enum virQEMUCapsFlags { QEMU_CAPS_OBJECT_RNG_RANDOM = 130, /* the rng-random backend for virtio rng */ QEMU_CAPS_OBJECT_RNG_EGD = 131, /* EGD protocol daemon for rng */ + QEMU_CAPS_SCSI_GENERIC = 132, /* -device scsi-generic */ + QEMU_CAPS_SCSI_HOST_BOOTINDEX = 133, /* scsi-generic.bootindex */
Why it's named as "SCSI_HOST_BOOTINDEX", but the comment says "scsi-generic.bootindex"? It's a confused, as we also have terms like "SCSI_HOST" for "scsi-host" across.
QEMU_CAPS_LAST, /* this must always be the last item */ };

For scsi-generic, the command line will be like: -drive file=/dev/sg0,if=none,id=drive-hostdev-scsi0-0-0-0 -device scsi-generic,bus=scsi0.0,channel=0,scsi-id=4,lun=8,drive=drive-hostdev-scsi0-0-0-0,id=hostdev-scsi0-0-0-0 The relationship between the libvirt address attrs and the qdev properties are(channel should always be 0): bus=scsi<controller>.0 scsi-id=<target> lun=<unit> --- src/qemu/qemu_command.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 153 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 5eb9999..1d2540e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -49,6 +49,8 @@ #include <sys/stat.h> #include <fcntl.h> +#include <dirent.h> +#include <sys/types.h> #define VIR_FROM_THIS VIR_FROM_QEMU @@ -651,7 +653,16 @@ qemuAssignDeviceHostdevAlias(virDomainDefPtr def, virDomainHostdevDefPtr hostdev } } - if (virAsprintf(&hostdev->info->alias, "hostdev%d", idx) < 0) { + if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) { + if (virAsprintf(&hostdev->info->alias, "hostdev-scsi%d-%d-%d-%d", + hostdev->source.subsys.u.scsi.adapter, + hostdev->source.subsys.u.scsi.bus, + hostdev->source.subsys.u.scsi.target, + hostdev->source.subsys.u.scsi.unit) < 0) { + virReportOOMError(); + return -1; + } + } else if (virAsprintf(&hostdev->info->alias, "hostdev%d", idx) < 0) { virReportOOMError(); return -1; } @@ -3864,6 +3875,110 @@ qemuBuildUSBHostdevUsbDevStr(virDomainHostdevDefPtr dev) return ret; } +static int +scsiGetDeviceId(unsigned int adapter, + unsigned int bus, + unsigned int target, + unsigned int unit) +{ + DIR *dir = NULL; + struct dirent *entry; + char *path; + int id; + + if (virAsprintf(&path, + "/sys/bus/scsi/devices/target%d:%d:%d/%d:%d:%d:%d/scsi_generic", + adapter, bus, target, adapter, bus, target, unit) < 0) { + virReportOOMError(); + return -1; + } + dir = opendir(path); + VIR_FREE(path); + if (!dir) { + VIR_WARN("Failed to open %s", path); + return -1; + } + + while ((entry = readdir(dir))) { + if (entry->d_name[0] == '.') + continue; + + if (sscanf(entry->d_name, "sg%d", &id) != 1) { + VIR_WARN("Failed to analyse sg id"); + return -1; + } + } + + return id; +} + +static char * +qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev, virQEMUCapsPtr qemuCaps) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + int scsiid; + + if ((scsiid = scsiGetDeviceId(dev->source.subsys.u.scsi.adapter, + dev->source.subsys.u.scsi.bus, + dev->source.subsys.u.scsi.target, + dev->source.subsys.u.scsi.unit)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("can't get sg* number")); + goto error; + } + + virBufferAsprintf(&buf, "file=/dev/sg%d,if=none", scsiid); + virBufferAsprintf(&buf, ",id=%s-%s", + virDomainDeviceAddressTypeToString(dev->info->type), + dev->info->alias); + if (dev->info->readonly && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_READONLY)) + virBufferAsprintf(&buf, ",readonly=on"); + + return virBufferContentAndReset(&buf); +error: + virBufferFreeAndReset(&buf); + return NULL; +} + + +static char * +qemuBuildSCSIHostdevDevStr(virDomainDefPtr def, virDomainHostdevDefPtr dev, + virQEMUCapsPtr qemuCaps) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + int controllerModel = -1; + + controllerModel = virDomainInfoFindControllerModel(def, dev->info, + VIR_DOMAIN_CONTROLLER_TYPE_SCSI); + if (qemuSetScsiControllerModel(def, qemuCaps, &controllerModel) < 0) + goto error; + /* TODO: deal with lsi or ibm controller */ + if (controllerModel == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI) { + virBufferAsprintf(&buf, "scsi-generic"); + if (dev->info->addr.drive.bus != 0) + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("SCSI controller only supports 1 bus")); + /* TODO: deal with early version qemu which does not support bus... */ + virBufferAsprintf(&buf, + ",bus=scsi%d.0,channel=0,scsi-id=%d,lun=%d", + dev->info->addr.drive.controller, + dev->info->addr.drive.target, + dev->info->addr.drive.unit); + virBufferAsprintf(&buf, ",drive=%s-%s,id=%s", + virDomainDeviceAddressTypeToString(dev->info->type), + dev->info->alias, dev->info->alias); + if (dev->info->bootIndex) + virBufferAsprintf(&buf, ",bootindex=%d", dev->info->bootIndex); + } else { + goto error; + } + + return virBufferContentAndReset(&buf); +error: + virBufferFreeAndReset(&buf); + return NULL; +} /* This function outputs a -chardev command line option which describes only the @@ -6953,10 +7068,11 @@ qemuBuildCommandLine(virConnectPtr conn, if (hostdev->info->bootIndex) { if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && - hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)) { + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB && + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("booting from assigned devices is only" - " supported for PCI and USB devices")); + " supported for PCI, USB and SCSI devices")); goto error; } else { if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI && @@ -6973,6 +7089,40 @@ qemuBuildCommandLine(virConnectPtr conn, " supported with this version of qemu")); goto error; } + if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI && + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_HOST_BOOTINDEX)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("booting from assigned SCSI devices is not" + " supported with this version of qemu")); + goto error; + } + } + } + + /* SCSI */ + if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && + hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) { + /* TODO */ + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE) && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE) && + virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_GENERIC)) { + char *drvstr; + + virCommandAddArg(cmd, "-drive"); + if (!(drvstr = qemuBuildSCSIHostdevDrvStr(hostdev, qemuCaps))) + goto error; + virCommandAddArg(cmd, drvstr); + VIR_FREE(drvstr); + + virCommandAddArg(cmd, "-device"); + if (!(devstr = qemuBuildSCSIHostdevDevStr(def, hostdev, qemuCaps))) + goto error; + virCommandAddArg(cmd, devstr); + VIR_FREE(devstr); + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("SCSI assignment is not supported by this version of qemu")); + goto error; } } -- 1.7.1

On 2013年03月04日 14:01, Han Cheng wrote:
For scsi-generic, the command line will be like:
-drive file=/dev/sg0,if=none,id=drive-hostdev-scsi0-0-0-0 -device scsi-generic,bus=scsi0.0,channel=0,scsi-id=4,lun=8,drive=drive-hostdev-scsi0-0-0-0,id=hostdev-scsi0-0-0-0
The relationship between the libvirt address attrs and the qdev properties are(channel should always be 0): bus=scsi<controller>.0 scsi-id=<target> lun=<unit> --- src/qemu/qemu_command.c | 156 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 153 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 5eb9999..1d2540e 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -49,6 +49,8 @@
#include<sys/stat.h> #include<fcntl.h> +#include<dirent.h> +#include<sys/types.h>
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -651,7 +653,16 @@ qemuAssignDeviceHostdevAlias(virDomainDefPtr def, virDomainHostdevDefPtr hostdev } }
- if (virAsprintf(&hostdev->info->alias, "hostdev%d", idx)< 0) { + if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) { + if (virAsprintf(&hostdev->info->alias, "hostdev-scsi%d-%d-%d-%d", + hostdev->source.subsys.u.scsi.adapter, + hostdev->source.subsys.u.scsi.bus, + hostdev->source.subsys.u.scsi.target, + hostdev->source.subsys.u.scsi.unit)< 0) { + virReportOOMError(); + return -1; + } + } else if (virAsprintf(&hostdev->info->alias, "hostdev%d", idx)< 0) { virReportOOMError(); return -1; } @@ -3864,6 +3875,110 @@ qemuBuildUSBHostdevUsbDevStr(virDomainHostdevDefPtr dev) return ret; }
+static int +scsiGetDeviceId(unsigned int adapter, + unsigned int bus, + unsigned int target, + unsigned int unit)
This should be a util function, and note that it's Linux platform specific.
+{ + DIR *dir = NULL; + struct dirent *entry; + char *path; + int id;
s/int/unsigned int/,
+ + if (virAsprintf(&path, + "/sys/bus/scsi/devices/target%d:%d:%d/%d:%d:%d:%d/scsi_generic", + adapter, bus, target, adapter, bus, target, unit)< 0) { + virReportOOMError(); + return -1; + } + dir = opendir(path); + VIR_FREE(path); + if (!dir) {
if (!(dir = opendir(path)))
+ VIR_WARN("Failed to open %s", path);
Any special reason for this to be a warning, but not an error instead?
+ return -1; + } + + while ((entry = readdir(dir))) { + if (entry->d_name[0] == '.') + continue; + + if (sscanf(entry->d_name, "sg%d",&id) != 1) { + VIR_WARN("Failed to analyse sg id"); + return -1;
Since here it returns -1, above should be an error.
+ } + } + + return id; +} + +static char * +qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev, virQEMUCapsPtr qemuCaps) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + int scsiid; + + if ((scsiid = scsiGetDeviceId(dev->source.subsys.u.scsi.adapter, + dev->source.subsys.u.scsi.bus, + dev->source.subsys.u.scsi.target, + dev->source.subsys.u.scsi.unit))< 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("can't get sg* number"));
"*" is magic in the error message. s/sg\*/sg/, And actually if you throw error in scsiGetDeviceId, there is no need to report error here anymore.
+ goto error; + } + + virBufferAsprintf(&buf, "file=/dev/sg%d,if=none", scsiid); + virBufferAsprintf(&buf, ",id=%s-%s", + virDomainDeviceAddressTypeToString(dev->info->type), + dev->info->alias); + if (dev->info->readonly&& + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE_READONLY)) + virBufferAsprintf(&buf, ",readonly=on"); + + return virBufferContentAndReset(&buf);
Should check if there is any error of the buf here. Something like: if (virBufferError(&buf)) { virReportOOMErrorr(); goto error; }
+error: + virBufferFreeAndReset(&buf); + return NULL; +} + + +static char * +qemuBuildSCSIHostdevDevStr(virDomainDefPtr def, virDomainHostdevDefPtr dev, + virQEMUCapsPtr qemuCaps) +{ + virBuffer buf = VIR_BUFFER_INITIALIZER; + int controllerModel = -1; + + controllerModel = virDomainInfoFindControllerModel(def, dev->info, + VIR_DOMAIN_CONTROLLER_TYPE_SCSI); + if (qemuSetScsiControllerModel(def, qemuCaps,&controllerModel)< 0) + goto error; + /* TODO: deal with lsi or ibm controller */ + if (controllerModel == VIR_DOMAIN_CONTROLLER_MODEL_SCSI_VIRTIO_SCSI) { + virBufferAsprintf(&buf, "scsi-generic"); + if (dev->info->addr.drive.bus != 0) + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("SCSI controller only supports 1 bus"));
XML_ERROR here might be better.
+ /* TODO: deal with early version qemu which does not support bus... */ + virBufferAsprintf(&buf, + ",bus=scsi%d.0,channel=0,scsi-id=%d,lun=%d", + dev->info->addr.drive.controller, + dev->info->addr.drive.target, + dev->info->addr.drive.unit); + virBufferAsprintf(&buf, ",drive=%s-%s,id=%s", + virDomainDeviceAddressTypeToString(dev->info->type), + dev->info->alias, dev->info->alias); + if (dev->info->bootIndex) + virBufferAsprintf(&buf, ",bootindex=%d", dev->info->bootIndex); + } else { + goto error;
This is magic, you need to give an error message here.
+ } + + return virBufferContentAndReset(&buf);
Need to check if there is error of buf too here.
+error: + virBufferFreeAndReset(&buf); + return NULL; +}
/* This function outputs a -chardev command line option which describes only the @@ -6953,10 +7068,11 @@ qemuBuildCommandLine(virConnectPtr conn, if (hostdev->info->bootIndex) { if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI&& - hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)) { + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB&& + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("booting from assigned devices is only" - " supported for PCI and USB devices")); + " supported for PCI, USB and SCSI devices")); goto error; } else { if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI&& @@ -6973,6 +7089,40 @@ qemuBuildCommandLine(virConnectPtr conn, " supported with this version of qemu")); goto error; } + if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI&& + !virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_HOST_BOOTINDEX)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("booting from assigned SCSI devices is not" + " supported with this version of qemu")); + goto error; + } + } + } + + /* SCSI */ + if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS&& + hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) { + /* TODO */ + if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DRIVE)&& + virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)&& + virQEMUCapsGet(qemuCaps, QEMU_CAPS_SCSI_GENERIC)) { + char *drvstr; + + virCommandAddArg(cmd, "-drive"); + if (!(drvstr = qemuBuildSCSIHostdevDrvStr(hostdev, qemuCaps))) + goto error; + virCommandAddArg(cmd, drvstr); + VIR_FREE(drvstr); + + virCommandAddArg(cmd, "-device"); + if (!(devstr = qemuBuildSCSIHostdevDevStr(def, hostdev, qemuCaps))) + goto error; + virCommandAddArg(cmd, devstr); + VIR_FREE(devstr); + } else { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("SCSI assignment is not supported by this version of qemu"));
In libvirt, we use "passthrough", instead of "assignment".
+ goto error; } }

--- docs/formatdomain.html.in | 36 ++++++++++++++++---- tests/qemuhelpdata/qemu-1.0-device | 10 +++++ tests/qemuhelpdata/qemu-1.1.0-device | 10 +++++ tests/qemuhelpdata/qemu-1.2.0-device | 5 +++ tests/qemuhelpdata/qemu-kvm-1.2.0-device | 5 +++ tests/qemuhelptest.c | 19 ++++++++--- .../qemuxml2argv-hostdev-scsi-address-boot.args | 9 +++++ .../qemuxml2argv-hostdev-scsi-address-boot.xml | 34 ++++++++++++++++++ ...qemuxml2argv-hostdev-scsi-address-readonly.args | 9 +++++ .../qemuxml2argv-hostdev-scsi-address-readonly.xml | 35 +++++++++++++++++++ .../qemuxml2argv-hostdev-scsi-address.args | 9 +++++ .../qemuxml2argv-hostdev-scsi-address.xml | 34 ++++++++++++++++++ tests/qemuxml2argvtest.c | 12 ++++++ tests/qemuxml2xmltest.c | 4 ++ 14 files changed, 219 insertions(+), 12 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 1835b39..57a2e8a 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2136,13 +2136,13 @@ <h4><a name="elementsHostDev">Host device assignment</a></h4> - <h5><a href="elementsHostDevSubsys">USB / PCI devices</a></h5> + <h5><a href="elementsHostDevSubsys">USB / PCI /SCSI devices</a></h5> <p> - USB and PCI devices attached to the host can be passed through + USB, PCI and SCSI devices attached to the host can be passed through to the guest using the <code>hostdev</code> element. - <span class="since">since after 0.4.4 for USB and 0.6.0 for PCI - (KVM only)</span>: + <span class="since">since after 0.4.4 for USB, 0.6.0 for PCI and + 0.13.0 for SCSI(KVM only)</span>: </p> <pre> @@ -2168,17 +2168,34 @@ <address bus='0x06' slot='0x02' function='0x0'/> </source> <boot order='1'/> + <readonly/> <rom bar='on' file='/etc/fake/boot.bin'/> </hostdev> </devices> ...</pre> + <p>or:</p> + +<pre> + ... + <devices> + <hostdev mode='subsystem' type='scsi'> + <source> + <adapter name='scsi_host0'/> + <address type='scsi' bus='0' target='0' unit='0'/> + </source> + <address type='scsi' controller= '0' bus='0' target='0' unit='0'/> + </hostdev> + </devices> + ...</pre> + <dl> <dt><code>hostdev</code></dt> <dd>The <code>hostdev</code> element is the main container for describing host devices. For usb device passthrough <code>mode</code> is always - "subsystem" and <code>type</code> is "usb" for a USB device and "pci" - for a PCI device. When <code>managed</code> is "yes" for a PCI + "subsystem" and <code>type</code> is "usb" for a USB device, "pci" + for a PCI device and "scsi" for a SCSI device. When + <code>managed</code> is "yes" for a PCI device, it is detached from the host before being passed on to the guest, and reattached to the host after the guest exits. If <code>managed</code> is omitted or "no", and for USB @@ -2188,7 +2205,8 @@ hot-plugging the device, and <code>virNodeDeviceReAttach</code> (or <code>virsh nodedev-reattach</code>) after hot-unplug or stopping the - guest.</dd> + guest.For SCSI device, user is responsible to make sure do not + use this device</dd> <dt><code>source</code></dt> <dd>The source element describes the device as seen from the host. The USB device can either be addressed by vendor / product id using the @@ -2221,6 +2239,9 @@ <code>id</code> attribute that specifies the USB vendor and product id. The ids can be given in decimal, hexadecimal (starting with 0x) or octal (starting with 0) form.</dd> + <dt><code>readonly</code></dt> + <dd>Specifies that the device is readonly. + <span class="since">Since 0.13.0</span> for SCSI devices. <dt><code>boot</code></dt> <dd>Specifies that the device is bootable. The <code>order</code> attribute determines the order in which devices will be tried during @@ -2229,6 +2250,7 @@ <a href="#elementsOSBIOS">BIOS bootloader</a> section. <span class="since">Since 0.8.8</span> for PCI devices, <span class="since">Since 1.0.1</span> for USB devices. + <span class="since">Since 1.0.0</span> for SCSI devices. <dt><code>rom</code></dt> <dd>The <code>rom</code> element is used to change how a PCI device's ROM is presented to the guest. The optional <code>bar</code> diff --git a/tests/qemuhelpdata/qemu-1.0-device b/tests/qemuhelpdata/qemu-1.0-device index 0bdfbbd..d557f0e 100644 --- a/tests/qemuhelpdata/qemu-1.0-device +++ b/tests/qemuhelpdata/qemu-1.0-device @@ -136,3 +136,13 @@ virtio-net-pci.romfile=string virtio-net-pci.rombar=uint32 virtio-net-pci.multifunction=on/off virtio-net-pci.command_serr_enable=on/off +scsi-generic.drive=drive +scsi-generic.logical_block_size=uint16 +scsi-generic.physical_block_size=uint16 +scsi-generic.min_io_size=uint16 +scsi-generic.opt_io_size=uint32 +scsi-generic.bootindex=int32 +scsi-generic.discard_granularity=uint32 +scsi-generic.channel=uint32 +scsi-generic.scsi-id=uint32 +scsi-generic.lun=uint32 diff --git a/tests/qemuhelpdata/qemu-1.1.0-device b/tests/qemuhelpdata/qemu-1.1.0-device index abbf850..7313a34 100644 --- a/tests/qemuhelpdata/qemu-1.1.0-device +++ b/tests/qemuhelpdata/qemu-1.1.0-device @@ -158,3 +158,13 @@ scsi-disk.dpofua=on/off scsi-disk.channel=uint32 scsi-disk.scsi-id=uint32 scsi-disk.lun=uint32 +scsi-generic.drive=drive +scsi-generic.logical_block_size=blocksize +scsi-generic.physical_block_size=blocksize +scsi-generic.min_io_size=uint16 +scsi-generic.opt_io_size=uint32 +scsi-generic.bootindex=int32 +scsi-generic.discard_granularity=uint32 +scsi-generic.channel=uint32 +scsi-generic.scsi-id=uint32 +scsi-generic.lun=uint32 diff --git a/tests/qemuhelpdata/qemu-1.2.0-device b/tests/qemuhelpdata/qemu-1.2.0-device index 5613e00..40845e4 100644 --- a/tests/qemuhelpdata/qemu-1.2.0-device +++ b/tests/qemuhelpdata/qemu-1.2.0-device @@ -208,3 +208,8 @@ usb-host.bootindex=int32 usb-host.pipeline=on/off usb-host.port=string usb-host.full-path=on/off +scsi-generic.drive=drive +scsi-generic.bootindex=int32 +scsi-generic.channel=uint32 +scsi-generic.scsi-id=uint32 +scsi-generic.lun=uint32 diff --git a/tests/qemuhelpdata/qemu-kvm-1.2.0-device b/tests/qemuhelpdata/qemu-kvm-1.2.0-device index 879a049..09e3ef7 100644 --- a/tests/qemuhelpdata/qemu-kvm-1.2.0-device +++ b/tests/qemuhelpdata/qemu-kvm-1.2.0-device @@ -220,3 +220,8 @@ usb-host.bootindex=int32 usb-host.pipeline=on/off usb-host.port=string usb-host.full-path=on/off +scsi-generic.drive=drive +scsi-generic.bootindex=int32 +scsi-generic.channel=uint32 +scsi-generic.scsi-id=uint32 +scsi-generic.lun=uint32 diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index 720a188..c3516dd 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -506,7 +506,8 @@ mymain(void) QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DEVICE_VMWARE_SVGA, QEMU_CAPS_DEVICE_USB_SERIAL, - QEMU_CAPS_DEVICE_USB_NET); + QEMU_CAPS_DEVICE_USB_NET, + QEMU_CAPS_SCSI_GENERIC); DO_TEST("qemu-kvm-0.12.1.2-rhel61", 12001, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -723,7 +724,9 @@ mymain(void) QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DEVICE_VMWARE_SVGA, QEMU_CAPS_DEVICE_USB_SERIAL, - QEMU_CAPS_DEVICE_USB_NET); + QEMU_CAPS_DEVICE_USB_NET, + QEMU_CAPS_SCSI_GENERIC, + QEMU_CAPS_SCSI_HOST_BOOTINDEX); DO_TEST("qemu-1.1.0", 1001000, 0, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -811,7 +814,9 @@ mymain(void) QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DEVICE_VMWARE_SVGA, QEMU_CAPS_DEVICE_USB_SERIAL, - QEMU_CAPS_DEVICE_USB_NET); + QEMU_CAPS_DEVICE_USB_NET, + QEMU_CAPS_SCSI_GENERIC, + QEMU_CAPS_SCSI_HOST_BOOTINDEX); DO_TEST("qemu-1.2.0", 1002000, 0, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -910,7 +915,9 @@ mymain(void) QEMU_CAPS_DEVICE_VMWARE_SVGA, QEMU_CAPS_DEVICE_VIDEO_PRIMARY, QEMU_CAPS_DEVICE_USB_SERIAL, - QEMU_CAPS_DEVICE_USB_NET); + QEMU_CAPS_DEVICE_USB_NET, + QEMU_CAPS_SCSI_GENERIC, + QEMU_CAPS_SCSI_HOST_BOOTINDEX); DO_TEST("qemu-kvm-1.2.0", 1002000, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -1014,7 +1021,9 @@ mymain(void) QEMU_CAPS_DEVICE_VMWARE_SVGA, QEMU_CAPS_DEVICE_VIDEO_PRIMARY, QEMU_CAPS_DEVICE_USB_SERIAL, - QEMU_CAPS_DEVICE_USB_NET); + QEMU_CAPS_DEVICE_USB_NET, + QEMU_CAPS_SCSI_GENERIC, + QEMU_CAPS_SCSI_HOST_BOOTINDEX); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.args new file mode 100644 index 0000000..d326f13 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.args @@ -0,0 +1,9 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ +unix:/tmp/test-monitor,server,nowait -no-acpi -device \ +virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 -usb -drive \ +file=/dev/HostVG/QEMUGuest2,if=none,id=drive-ide0-0-0 -device \ +ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 -drive \ +file=/dev/sg0,if=none,id=drive-hostdev-scsi0-0-0-0 -device \ +scsi-generic,bus=scsi0.0,channel=0,scsi-id=4,lun=8,drive=drive-hostdev-scsi0-0-0-0,id=hostdev-scsi0-0-0-0,bootindex=1 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.xml new file mode 100644 index 0000000..e3de719 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.xml @@ -0,0 +1,34 @@ +<domain type='qemu'> + <name>QEMUGuest2</name> + <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest2'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='scsi' index='0' model='virtio-scsi'/> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <hostdev mode='subsystem' type='scsi' managed='yes'> + <source> + <adapter name='scsi_host0'/> + <address bus='0' target='0' unit='0'/> + </source> + <boot order='1'/> + <address type='drive' controller='0' bus='0' target='4' unit='8'/> + </hostdev> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.args new file mode 100644 index 0000000..57ecdcb --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.args @@ -0,0 +1,9 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc \ +-m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ +unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device \ +virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 -usb -drive \ +file=/dev/HostVG/QEMUGuest2,if=none,id=drive-ide0-0-0 -device \ +ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 -drive \ +file=/dev/sg0,if=none,id=drive-hostdev-scsi0-0-0-0,readonly=on -device \ +scsi-generic,bus=scsi0.0,channel=0,scsi-id=4,lun=8,drive=drive-hostdev-scsi0-0-0-0,id=hostdev-scsi0-0-0-0 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.xml new file mode 100644 index 0000000..11d1712 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.xml @@ -0,0 +1,35 @@ +<domain type='qemu'> + <name>QEMUGuest2</name> + <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest2'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='scsi' index='0' model='virtio-scsi'/> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <hostdev mode='subsystem' type='scsi' managed='yes'> + <source> + <adapter name='scsi_host0'/> + <address bus='0' target='0' unit='0'/> + </source> + <readonly/> + <address type='drive' controller='0' bus='0' target='4' unit='8'/> + </hostdev> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.args new file mode 100644 index 0000000..8c7c5c7 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.args @@ -0,0 +1,9 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ +unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device \ +virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 -usb -drive \ +file=/dev/HostVG/QEMUGuest2,if=none,id=drive-ide0-0-0 -device \ +ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 -drive \ +file=/dev/sg0,if=none,id=drive-hostdev-scsi0-0-0-0 -device \ +scsi-generic,bus=scsi0.0,channel=0,scsi-id=4,lun=8,drive=drive-hostdev-scsi0-0-0-0,id=hostdev-scsi0-0-0-0 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.xml new file mode 100644 index 0000000..ccdbb0d --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.xml @@ -0,0 +1,34 @@ +<domain type='qemu'> + <name>QEMUGuest2</name> + <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static'>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest2'/> + <target dev='hda' bus='ide'/> + <address type='drive' controller='0' bus='0' target='0' unit='0'/> + </disk> + <controller type='scsi' index='0' model='virtio-scsi'/> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <hostdev mode='subsystem' type='scsi' managed='yes'> + <source> + <adapter name='scsi_host0'/> + <address bus='0' target='0' unit='0'/> + </source> + <address type='drive' controller='0' bus='0' target='4' unit='8'/> + </hostdev> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index b6b5489..33fe4f1 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -887,6 +887,18 @@ mymain(void) DO_TEST("virtio-rng-egd", QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_EGD); + DO_TEST("hostdev-scsi-address", + QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_VIRTIO_SCSI_PCI, QEMU_CAPS_SCSI_GENERIC); + DO_TEST("hostdev-scsi-address-boot", + QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_VIRTIO_SCSI_PCI, QEMU_CAPS_SCSI_GENERIC, + QEMU_CAPS_BOOTINDEX, QEMU_CAPS_SCSI_HOST_BOOTINDEX); + DO_TEST("hostdev-scsi-address-readonly", + QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_READONLY, + QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_VIRTIO_SCSI_PCI, QEMU_CAPS_SCSI_GENERIC); + virObjectUnref(driver.config); virObjectUnref(driver.caps); VIR_FREE(map); diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index d64960f..773c55f 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -261,6 +261,10 @@ mymain(void) DO_TEST_DIFFERENT("metadata"); + DO_TEST("hostdev-scsi-address"); + DO_TEST("hostdev-scsi-address-boot"); + DO_TEST("hostdev-scsi-address-readonly"); + virObjectUnref(driver.caps); return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE; -- 1.7.1

On 2013年03月04日 14:01, Han Cheng wrote:
--- docs/formatdomain.html.in | 36 ++++++++++++++++---- tests/qemuhelpdata/qemu-1.0-device | 10 +++++ tests/qemuhelpdata/qemu-1.1.0-device | 10 +++++ tests/qemuhelpdata/qemu-1.2.0-device | 5 +++ tests/qemuhelpdata/qemu-kvm-1.2.0-device | 5 +++ tests/qemuhelptest.c | 19 ++++++++--- .../qemuxml2argv-hostdev-scsi-address-boot.args | 9 +++++ .../qemuxml2argv-hostdev-scsi-address-boot.xml | 34 ++++++++++++++++++ ...qemuxml2argv-hostdev-scsi-address-readonly.args | 9 +++++ .../qemuxml2argv-hostdev-scsi-address-readonly.xml | 35 +++++++++++++++++++ .../qemuxml2argv-hostdev-scsi-address.args | 9 +++++ .../qemuxml2argv-hostdev-scsi-address.xml | 34 ++++++++++++++++++ tests/qemuxml2argvtest.c | 12 ++++++ tests/qemuxml2xmltest.c | 4 ++ 14 files changed, 219 insertions(+), 12 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
Oh, these stuffs should be foldered into the previous XML parsing and formating patches.
index 1835b39..57a2e8a 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2136,13 +2136,13 @@
<h4><a name="elementsHostDev">Host device assignment</a></h4>
-<h5><a href="elementsHostDevSubsys">USB / PCI devices</a></h5> +<h5><a href="elementsHostDevSubsys">USB / PCI /SCSI devices</a></h5>
<p> - USB and PCI devices attached to the host can be passed through + USB, PCI and SCSI devices attached to the host can be passed through to the guest using the<code>hostdev</code> element. -<span class="since">since after 0.4.4 for USB and 0.6.0 for PCI - (KVM only)</span>: +<span class="since">since after 0.4.4 for USB, 0.6.0 for PCI and + 0.13.0 for SCSI(KVM only)</span>: </p>
<pre> @@ -2168,17 +2168,34 @@ <address bus='0x06' slot='0x02' function='0x0'/> </source> <boot order='1'/> +<readonly/>
This should be in 1/5. Others should be in 2/5, or you can just merge 1/5 and 2/5 together, with these docs.
<rom bar='on' file='/etc/fake/boot.bin'/> </hostdev> </devices> ...</pre>
+<p>or:</p> + +<pre> + ... +<devices> +<hostdev mode='subsystem' type='scsi'> +<source> +<adapter name='scsi_host0'/> +<address type='scsi' bus='0' target='0' unit='0'/> +</source> +<address type='scsi' controller= '0' bus='0' target='0' unit='0'/> +</hostdev> +</devices> + ...</pre> + <dl> <dt><code>hostdev</code></dt> <dd>The<code>hostdev</code> element is the main container for describing host devices. For usb device passthrough<code>mode</code> is always - "subsystem" and<code>type</code> is "usb" for a USB device and "pci" - for a PCI device. When<code>managed</code> is "yes" for a PCI + "subsystem" and<code>type</code> is "usb" for a USB device, "pci" + for a PCI device and "scsi" for a SCSI device. When +<code>managed</code> is "yes" for a PCI device, it is detached from the host before being passed on to the guest, and reattached to the host after the guest exits. If<code>managed</code> is omitted or "no", and for USB @@ -2188,7 +2205,8 @@ hot-plugging the device, and<code>virNodeDeviceReAttach</code> (or<code>virsh nodedev-reattach</code>) after hot-unplug or stopping the - guest.</dd> + guest.For SCSI device, user is responsible to make sure do not + use this device</dd> <dt><code>source</code></dt> <dd>The source element describes the device as seen from the host. The USB device can either be addressed by vendor / product id using the @@ -2221,6 +2239,9 @@ <code>id</code> attribute that specifies the USB vendor and product id. The ids can be given in decimal, hexadecimal (starting with 0x) or octal (starting with 0) form.</dd> +<dt><code>readonly</code></dt> +<dd>Specifies that the device is readonly. +<span class="since">Since 0.13.0</span> for SCSI devices. <dt><code>boot</code></dt> <dd>Specifies that the device is bootable. The<code>order</code> attribute determines the order in which devices will be tried during @@ -2229,6 +2250,7 @@ <a href="#elementsOSBIOS">BIOS bootloader</a> section. <span class="since">Since 0.8.8</span> for PCI devices, <span class="since">Since 1.0.1</span> for USB devices. +<span class="since">Since 1.0.0</span> for SCSI devices. <dt><code>rom</code></dt> <dd>The<code>rom</code> element is used to change how a PCI device's ROM is presented to the guest. The optional<code>bar</code> diff --git a/tests/qemuhelpdata/qemu-1.0-device b/tests/qemuhelpdata/qemu-1.0-device index 0bdfbbd..d557f0e 100644 --- a/tests/qemuhelpdata/qemu-1.0-device +++ b/tests/qemuhelpdata/qemu-1.0-device @@ -136,3 +136,13 @@ virtio-net-pci.romfile=string virtio-net-pci.rombar=uint32 virtio-net-pci.multifunction=on/off virtio-net-pci.command_serr_enable=on/off +scsi-generic.drive=drive +scsi-generic.logical_block_size=uint16 +scsi-generic.physical_block_size=uint16 +scsi-generic.min_io_size=uint16 +scsi-generic.opt_io_size=uint32 +scsi-generic.bootindex=int32 +scsi-generic.discard_granularity=uint32 +scsi-generic.channel=uint32 +scsi-generic.scsi-id=uint32 +scsi-generic.lun=uint32 diff --git a/tests/qemuhelpdata/qemu-1.1.0-device b/tests/qemuhelpdata/qemu-1.1.0-device index abbf850..7313a34 100644 --- a/tests/qemuhelpdata/qemu-1.1.0-device +++ b/tests/qemuhelpdata/qemu-1.1.0-device @@ -158,3 +158,13 @@ scsi-disk.dpofua=on/off scsi-disk.channel=uint32 scsi-disk.scsi-id=uint32 scsi-disk.lun=uint32 +scsi-generic.drive=drive +scsi-generic.logical_block_size=blocksize +scsi-generic.physical_block_size=blocksize +scsi-generic.min_io_size=uint16 +scsi-generic.opt_io_size=uint32 +scsi-generic.bootindex=int32 +scsi-generic.discard_granularity=uint32 +scsi-generic.channel=uint32 +scsi-generic.scsi-id=uint32 +scsi-generic.lun=uint32 diff --git a/tests/qemuhelpdata/qemu-1.2.0-device b/tests/qemuhelpdata/qemu-1.2.0-device index 5613e00..40845e4 100644 --- a/tests/qemuhelpdata/qemu-1.2.0-device +++ b/tests/qemuhelpdata/qemu-1.2.0-device @@ -208,3 +208,8 @@ usb-host.bootindex=int32 usb-host.pipeline=on/off usb-host.port=string usb-host.full-path=on/off +scsi-generic.drive=drive +scsi-generic.bootindex=int32 +scsi-generic.channel=uint32 +scsi-generic.scsi-id=uint32 +scsi-generic.lun=uint32 diff --git a/tests/qemuhelpdata/qemu-kvm-1.2.0-device b/tests/qemuhelpdata/qemu-kvm-1.2.0-device index 879a049..09e3ef7 100644 --- a/tests/qemuhelpdata/qemu-kvm-1.2.0-device +++ b/tests/qemuhelpdata/qemu-kvm-1.2.0-device @@ -220,3 +220,8 @@ usb-host.bootindex=int32 usb-host.pipeline=on/off usb-host.port=string usb-host.full-path=on/off +scsi-generic.drive=drive +scsi-generic.bootindex=int32 +scsi-generic.channel=uint32 +scsi-generic.scsi-id=uint32 +scsi-generic.lun=uint32 diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index 720a188..c3516dd 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -506,7 +506,8 @@ mymain(void) QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DEVICE_VMWARE_SVGA, QEMU_CAPS_DEVICE_USB_SERIAL, - QEMU_CAPS_DEVICE_USB_NET); + QEMU_CAPS_DEVICE_USB_NET, + QEMU_CAPS_SCSI_GENERIC); DO_TEST("qemu-kvm-0.12.1.2-rhel61", 12001, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -723,7 +724,9 @@ mymain(void) QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DEVICE_VMWARE_SVGA, QEMU_CAPS_DEVICE_USB_SERIAL, - QEMU_CAPS_DEVICE_USB_NET); + QEMU_CAPS_DEVICE_USB_NET, + QEMU_CAPS_SCSI_GENERIC, + QEMU_CAPS_SCSI_HOST_BOOTINDEX); DO_TEST("qemu-1.1.0", 1001000, 0, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -811,7 +814,9 @@ mymain(void) QEMU_CAPS_DEVICE_CIRRUS_VGA, QEMU_CAPS_DEVICE_VMWARE_SVGA, QEMU_CAPS_DEVICE_USB_SERIAL, - QEMU_CAPS_DEVICE_USB_NET); + QEMU_CAPS_DEVICE_USB_NET, + QEMU_CAPS_SCSI_GENERIC, + QEMU_CAPS_SCSI_HOST_BOOTINDEX); DO_TEST("qemu-1.2.0", 1002000, 0, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -910,7 +915,9 @@ mymain(void) QEMU_CAPS_DEVICE_VMWARE_SVGA, QEMU_CAPS_DEVICE_VIDEO_PRIMARY, QEMU_CAPS_DEVICE_USB_SERIAL, - QEMU_CAPS_DEVICE_USB_NET); + QEMU_CAPS_DEVICE_USB_NET, + QEMU_CAPS_SCSI_GENERIC, + QEMU_CAPS_SCSI_HOST_BOOTINDEX); DO_TEST("qemu-kvm-1.2.0", 1002000, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -1014,7 +1021,9 @@ mymain(void) QEMU_CAPS_DEVICE_VMWARE_SVGA, QEMU_CAPS_DEVICE_VIDEO_PRIMARY, QEMU_CAPS_DEVICE_USB_SERIAL, - QEMU_CAPS_DEVICE_USB_NET); + QEMU_CAPS_DEVICE_USB_NET, + QEMU_CAPS_SCSI_GENERIC, + QEMU_CAPS_SCSI_HOST_BOOTINDEX);
return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.args new file mode 100644 index 0000000..d326f13 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.args
IMHO the name should be hostdev-scsi-generic. Or just hostdev-scsi
@@ -0,0 +1,9 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ +unix:/tmp/test-monitor,server,nowait -no-acpi -device \ +virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 -usb -drive \ +file=/dev/HostVG/QEMUGuest2,if=none,id=drive-ide0-0-0 -device \ +ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 -drive \ +file=/dev/sg0,if=none,id=drive-hostdev-scsi0-0-0-0 -device \ +scsi-generic,bus=scsi0.0,channel=0,scsi-id=4,lun=8,drive=drive-hostdev-scsi0-0-0-0,id=hostdev-scsi0-0-0-0,bootindex=1 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.xml new file mode 100644 index 0000000..e3de719 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.xml @@ -0,0 +1,34 @@ +<domain type='qemu'> +<name>QEMUGuest2</name> +<uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid> +<memory unit='KiB'>219100</memory> +<currentMemory unit='KiB'>219100</currentMemory> +<vcpu placement='static'>1</vcpu> +<os> +<type arch='i686' machine='pc'>hvm</type> +</os> +<clock offset='utc'/> +<on_poweroff>destroy</on_poweroff> +<on_reboot>restart</on_reboot> +<on_crash>destroy</on_crash> +<devices> +<emulator>/usr/bin/qemu</emulator> +<disk type='block' device='disk'> +<source dev='/dev/HostVG/QEMUGuest2'/> +<target dev='hda' bus='ide'/> +<address type='drive' controller='0' bus='0' target='0' unit='0'/> +</disk> +<controller type='scsi' index='0' model='virtio-scsi'/> +<controller type='usb' index='0'/> +<controller type='ide' index='0'/> +<hostdev mode='subsystem' type='scsi' managed='yes'> +<source> +<adapter name='scsi_host0'/> +<address bus='0' target='0' unit='0'/> +</source> +<boot order='1'/> +<address type='drive' controller='0' bus='0' target='4' unit='8'/> +</hostdev> +<memballoon model='virtio'/> +</devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.args new file mode 100644 index 0000000..57ecdcb --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.args @@ -0,0 +1,9 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc \ +-m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ +unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device \ +virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 -usb -drive \ +file=/dev/HostVG/QEMUGuest2,if=none,id=drive-ide0-0-0 -device \ +ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 -drive \ +file=/dev/sg0,if=none,id=drive-hostdev-scsi0-0-0-0,readonly=on -device \ +scsi-generic,bus=scsi0.0,channel=0,scsi-id=4,lun=8,drive=drive-hostdev-scsi0-0-0-0,id=hostdev-scsi0-0-0-0 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.xml new file mode 100644 index 0000000..11d1712 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.xml @@ -0,0 +1,35 @@ +<domain type='qemu'> +<name>QEMUGuest2</name> +<uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid> +<memory unit='KiB'>219100</memory> +<currentMemory unit='KiB'>219100</currentMemory> +<vcpu placement='static'>1</vcpu> +<os> +<type arch='i686' machine='pc'>hvm</type> +<boot dev='hd'/> +</os> +<clock offset='utc'/> +<on_poweroff>destroy</on_poweroff> +<on_reboot>restart</on_reboot> +<on_crash>destroy</on_crash> +<devices> +<emulator>/usr/bin/qemu</emulator> +<disk type='block' device='disk'> +<source dev='/dev/HostVG/QEMUGuest2'/> +<target dev='hda' bus='ide'/> +<address type='drive' controller='0' bus='0' target='0' unit='0'/> +</disk> +<controller type='scsi' index='0' model='virtio-scsi'/> +<controller type='usb' index='0'/> +<controller type='ide' index='0'/> +<hostdev mode='subsystem' type='scsi' managed='yes'> +<source> +<adapter name='scsi_host0'/> +<address bus='0' target='0' unit='0'/> +</source> +<readonly/> +<address type='drive' controller='0' bus='0' target='4' unit='8'/> +</hostdev> +<memballoon model='virtio'/> +</devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.args new file mode 100644 index 0000000..8c7c5c7 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.args
and hostdev-scsi-generic-readonly, or hostdev-scsi-readonly.
@@ -0,0 +1,9 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ +unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device \ +virtio-scsi-pci,id=scsi0,bus=pci.0,addr=0x3 -usb -drive \ +file=/dev/HostVG/QEMUGuest2,if=none,id=drive-ide0-0-0 -device \ +ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 -drive \ +file=/dev/sg0,if=none,id=drive-hostdev-scsi0-0-0-0 -device \ +scsi-generic,bus=scsi0.0,channel=0,scsi-id=4,lun=8,drive=drive-hostdev-scsi0-0-0-0,id=hostdev-scsi0-0-0-0 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.xml new file mode 100644 index 0000000..ccdbb0d --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.xml @@ -0,0 +1,34 @@ +<domain type='qemu'> +<name>QEMUGuest2</name> +<uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid> +<memory unit='KiB'>219100</memory> +<currentMemory unit='KiB'>219100</currentMemory> +<vcpu placement='static'>1</vcpu> +<os> +<type arch='i686' machine='pc'>hvm</type> +<boot dev='hd'/> +</os> +<clock offset='utc'/> +<on_poweroff>destroy</on_poweroff> +<on_reboot>restart</on_reboot> +<on_crash>destroy</on_crash> +<devices> +<emulator>/usr/bin/qemu</emulator> +<disk type='block' device='disk'> +<source dev='/dev/HostVG/QEMUGuest2'/> +<target dev='hda' bus='ide'/> +<address type='drive' controller='0' bus='0' target='0' unit='0'/> +</disk> +<controller type='scsi' index='0' model='virtio-scsi'/> +<controller type='usb' index='0'/> +<controller type='ide' index='0'/> +<hostdev mode='subsystem' type='scsi' managed='yes'> +<source> +<adapter name='scsi_host0'/> +<address bus='0' target='0' unit='0'/> +</source> +<address type='drive' controller='0' bus='0' target='4' unit='8'/> +</hostdev> +<memballoon model='virtio'/> +</devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index b6b5489..33fe4f1 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -887,6 +887,18 @@ mymain(void) DO_TEST("virtio-rng-egd", QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_VIRTIO_RNG, QEMU_CAPS_OBJECT_RNG_EGD);
+ DO_TEST("hostdev-scsi-address", + QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_VIRTIO_SCSI_PCI, QEMU_CAPS_SCSI_GENERIC);
Do we need QEMU_CAPS_VIRTIO_SCSI_PCI and QEMU_CAPS_NODEFCONFIG?
+ DO_TEST("hostdev-scsi-address-boot", + QEMU_CAPS_DRIVE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_VIRTIO_SCSI_PCI, QEMU_CAPS_SCSI_GENERIC, + QEMU_CAPS_BOOTINDEX, QEMU_CAPS_SCSI_HOST_BOOTINDEX);
Likewise.
+ DO_TEST("hostdev-scsi-address-readonly", + QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_READONLY, + QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, + QEMU_CAPS_VIRTIO_SCSI_PCI, QEMU_CAPS_SCSI_GENERIC);
Likewise.
+ virObjectUnref(driver.config); virObjectUnref(driver.caps); VIR_FREE(map); diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index d64960f..773c55f 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -261,6 +261,10 @@ mymain(void)
DO_TEST_DIFFERENT("metadata");
+ DO_TEST("hostdev-scsi-address"); + DO_TEST("hostdev-scsi-address-boot"); + DO_TEST("hostdev-scsi-address-readonly"); + virObjectUnref(driver.caps);
return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;

On 2013年03月04日 14:01, Han Cheng wrote:
This patch series tried to implement the fifth part of Paolo's proposal:
http://permalink.gmane.org/gmane.comp.emulators.libvirt/50428
It is not completed. But it may for use.
Needs some more works on: src/qemu/qemu_hostdev.c src/qemu/qemu_hotplug.c We may also need create src/util/virscsi.[hc] like src/util/vir(pci|usb).[hc], add sg* to nodedev tree and some others.
As scsi hostdev needs -drive and -device like disk. There are two approaches: a) build a disk then use the disk related functions, b) create new function for it. I chose the last one as it is clearer and easier. But this may create some redundant codes.
You did right. Except the -drive and -device, I think the other properties are very different. Mixing them together with disk will be just confused.
Any ideas?
Han Cheng (5): conf: Introduce readonly to hostdev and change helper function conf: Introduce scsi hostdev qemu: New cap flag for scsi-generic qemu: Build qemu command line for scsi-generic tests: tests for scsi hostdev
docs/formatdomain.html.in | 36 +- docs/schemas/domaincommon.rng | 38 ++ src/conf/domain_audit.c | 10 src/conf/domain_conf.c | 167 +++++++++- src/conf/domain_conf.h | 13 src/libvirt_private.syms | 2 src/qemu/qemu_capabilities.c | 15 src/qemu/qemu_capabilities.h | 2 src/qemu/qemu_command.c | 160 +++++++++ tests/qemuhelpdata/qemu-1.0-device | 10 tests/qemuhelpdata/qemu-1.1.0-device | 10 tests/qemuhelpdata/qemu-1.2.0-device | 5 tests/qemuhelpdata/qemu-kvm-1.2.0-device | 5 tests/qemuhelptest.c | 19 - tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.args | 9 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-boot.xml | 34 ++ tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.args | 9 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address-readonly.xml | 35 ++ tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.args | 9 tests/qemuxml2argvdata/qemuxml2argv-hostdev-scsi-address.xml | 34 ++ tests/qemuxml2argvtest.c | 12 tests/qemuxml2xmltest.c | 4 22 files changed, 607 insertions(+), 31 deletions(-)
participants (2)
-
Han Cheng
-
Osier Yang