mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-03 17:47:15 +03:00
conf: Generate address for scsi host device automatically
With unknown good reasons, the attribute "bus" of scsi device address is always set to 0, same for attribute "target". (See virDomainDiskDefAssignAddress). Though we might need to change the algorithm to honor "bus" and "target" too, that's a different issue. The address generator for scsi host device in this patch just follows the unknown good reasons, only considering the "controller" and "unit". It walks through all scsi controllers and their units, to see if the address $controller:0:0:$unit can be used (if not used by any disk or scsi host device yet), if found one, it sits on it, otherwise, it creates a new controller (actually the controller is implicitly created by someone else), and sits on $new_controller:0:0:0 instead.
This commit is contained in:
parent
2ea45647bc
commit
cdb9789559
@ -3782,6 +3782,141 @@ cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check if a drive type address $controller:0:0:$unit is already
|
||||
* taken by a disk or not.
|
||||
*/
|
||||
static bool
|
||||
virDomainDriveAddressIsUsedByDisk(virDomainDefPtr def,
|
||||
enum virDomainDiskBus type,
|
||||
unsigned int controller,
|
||||
unsigned int unit)
|
||||
{
|
||||
virDomainDiskDefPtr disk;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < def->ndisks; i++) {
|
||||
disk = def->disks[i];
|
||||
|
||||
if (disk->bus != type ||
|
||||
disk->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE)
|
||||
continue;
|
||||
|
||||
if (disk->info.addr.drive.controller == controller &&
|
||||
disk->info.addr.drive.unit == unit &&
|
||||
disk->info.addr.drive.bus == 0 &&
|
||||
disk->info.addr.drive.target == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Check if a drive type address $controller:0:0:$unit is already
|
||||
* taken by a host device or not.
|
||||
*/
|
||||
static bool
|
||||
virDomainDriveAddressIsUsedByHostdev(virDomainDefPtr def,
|
||||
enum virDomainHostdevSubsysType type,
|
||||
unsigned int controller,
|
||||
unsigned int unit)
|
||||
{
|
||||
virDomainHostdevDefPtr hostdev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < def->nhostdevs; i++) {
|
||||
hostdev = def->hostdevs[i];
|
||||
|
||||
if (hostdev->source.subsys.type != type)
|
||||
continue;
|
||||
|
||||
if (hostdev->info->addr.drive.controller == controller &&
|
||||
hostdev->info->addr.drive.unit == unit &&
|
||||
hostdev->info->addr.drive.bus == 0 &&
|
||||
hostdev->info->addr.drive.target == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
virDomainSCSIDriveAddressIsUsed(virDomainDefPtr def,
|
||||
unsigned int controller,
|
||||
unsigned int unit)
|
||||
{
|
||||
/* In current implementation, the maximum unit number of a controller
|
||||
* is either 16 or 7 (narrow SCSI bus), and if the maximum unit number
|
||||
* is 16, the controller itself is on unit 7 */
|
||||
if (unit == 7)
|
||||
return true;
|
||||
|
||||
if (virDomainDriveAddressIsUsedByDisk(def, VIR_DOMAIN_DISK_BUS_SCSI,
|
||||
controller, unit) ||
|
||||
virDomainDriveAddressIsUsedByHostdev(def, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI,
|
||||
controller, unit))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Find out the next usable "unit" of a specific controller */
|
||||
static int
|
||||
virDomainControllerSCSINextUnit(virDomainDefPtr def,
|
||||
unsigned int max_unit,
|
||||
unsigned int controller)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < max_unit; i++) {
|
||||
if (!virDomainSCSIDriveAddressIsUsed(def, controller, i))
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define SCSI_WIDE_BUS_MAX_CONT_UNIT 16
|
||||
#define SCSI_NARROW_BUS_MAX_CONT_UNIT 7
|
||||
|
||||
static int
|
||||
virDomainHostdevAssignAddress(virDomainXMLOptionPtr xmlopt,
|
||||
virDomainDefPtr def,
|
||||
virDomainHostdevDefPtr hostdev)
|
||||
{
|
||||
int next_unit;
|
||||
unsigned nscsi_controllers = 0;
|
||||
bool found = false;
|
||||
int i;
|
||||
|
||||
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < def->ncontrollers && !found; i++) {
|
||||
if (def->controllers[i]->type != VIR_DOMAIN_CONTROLLER_TYPE_SCSI)
|
||||
continue;
|
||||
|
||||
nscsi_controllers++;
|
||||
next_unit = virDomainControllerSCSINextUnit(def,
|
||||
xmlopt->config.hasWideScsiBus ?
|
||||
SCSI_WIDE_BUS_MAX_CONT_UNIT :
|
||||
SCSI_NARROW_BUS_MAX_CONT_UNIT,
|
||||
def->controllers[i]->idx);
|
||||
if (next_unit >= 0)
|
||||
found = true;
|
||||
}
|
||||
|
||||
hostdev->info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE;
|
||||
|
||||
hostdev->info->addr.drive.controller = found ?
|
||||
def->controllers[i - 1]->idx :
|
||||
nscsi_controllers;
|
||||
hostdev->info->addr.drive.bus = 0;
|
||||
hostdev->info->addr.drive.target = 0;
|
||||
hostdev->info->addr.drive.unit = found ? next_unit : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
|
||||
xmlXPathContextPtr ctxt,
|
||||
@ -8802,7 +8937,9 @@ error:
|
||||
}
|
||||
|
||||
static virDomainHostdevDefPtr
|
||||
virDomainHostdevDefParseXML(const xmlNodePtr node,
|
||||
virDomainHostdevDefParseXML(virDomainXMLOptionPtr xmlopt,
|
||||
virDomainDefPtr vmdef,
|
||||
const xmlNodePtr node,
|
||||
xmlXPathContextPtr ctxt,
|
||||
virHashTablePtr bootHash,
|
||||
unsigned int flags)
|
||||
@ -8862,7 +8999,9 @@ virDomainHostdevDefParseXML(const xmlNodePtr node,
|
||||
}
|
||||
break;
|
||||
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
|
||||
if (def->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
|
||||
if (def->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
|
||||
virDomainHostdevAssignAddress(xmlopt, vmdef, def) < 0) {
|
||||
|
||||
virReportError(VIR_ERR_XML_ERROR, "%s",
|
||||
_("SCSI host devices must have address specified"));
|
||||
goto error;
|
||||
@ -9271,8 +9410,8 @@ virDomainDeviceDefParse(const char *xmlStr,
|
||||
goto error;
|
||||
} else if (xmlStrEqual(node->name, BAD_CAST "hostdev")) {
|
||||
dev->type = VIR_DOMAIN_DEVICE_HOSTDEV;
|
||||
if (!(dev->data.hostdev = virDomainHostdevDefParseXML(node, ctxt, NULL,
|
||||
flags)))
|
||||
if (!(dev->data.hostdev = virDomainHostdevDefParseXML(xmlopt, def, node,
|
||||
ctxt, NULL, flags)))
|
||||
goto error;
|
||||
} else if (xmlStrEqual(node->name, BAD_CAST "controller")) {
|
||||
dev->type = VIR_DOMAIN_DEVICE_CONTROLLER;
|
||||
@ -10255,6 +10394,30 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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, -1) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static virDomainDefPtr
|
||||
virDomainDefParseXML(xmlDocPtr xml,
|
||||
@ -11618,7 +11781,8 @@ virDomainDefParseXML(xmlDocPtr xml,
|
||||
for (i = 0; i < n; i++) {
|
||||
virDomainHostdevDefPtr hostdev;
|
||||
|
||||
hostdev = virDomainHostdevDefParseXML(nodes[i], ctxt, bootHash, flags);
|
||||
hostdev = virDomainHostdevDefParseXML(xmlopt, def, nodes[i],
|
||||
ctxt, bootHash, flags);
|
||||
if (!hostdev)
|
||||
goto error;
|
||||
|
||||
@ -11631,6 +11795,9 @@ virDomainDefParseXML(xmlDocPtr xml,
|
||||
}
|
||||
|
||||
def->hostdevs[def->nhostdevs++] = hostdev;
|
||||
|
||||
if (virDomainDefMaybeAddHostdevSCSIcontroller(def) < 0)
|
||||
goto error;
|
||||
}
|
||||
VIR_FREE(nodes);
|
||||
|
||||
@ -13232,31 +13399,6 @@ 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, -1) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Based on the declared <address/> info for any devices,
|
||||
* add necessary drive controllers which are not already present
|
||||
|
@ -0,0 +1,95 @@
|
||||
<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'/>
|
||||
<controller type='pci' index='0' model='pci-root'/>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host0'/>
|
||||
<address bus='0' target='0' unit='0'/>
|
||||
</source>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host1'/>
|
||||
<address bus='0' target='0' unit='1'/>
|
||||
</source>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host2'/>
|
||||
<address bus='0' target='0' unit='2'/>
|
||||
</source>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host3'/>
|
||||
<address bus='0' target='0' unit='3'/>
|
||||
</source>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host4'/>
|
||||
<address bus='0' target='0' unit='4'/>
|
||||
</source>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host5'/>
|
||||
<address bus='0' target='0' unit='5'/>
|
||||
</source>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host6'/>
|
||||
<address bus='0' target='0' unit='6'/>
|
||||
</source>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host7'/>
|
||||
<address bus='0' target='0' unit='7'/>
|
||||
</source>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host8'/>
|
||||
<address bus='0' target='0' unit='8'/>
|
||||
</source>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host9'/>
|
||||
<address bus='0' target='0' unit='9'/>
|
||||
</source>
|
||||
<address type='drive' controller='1' bus='0' target='0' unit='5'/>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host10'/>
|
||||
<address bus='0' target='0' unit='10'/>
|
||||
</source>
|
||||
</hostdev>
|
||||
<memballoon model='virtio'/>
|
||||
</devices>
|
||||
</domain>
|
@ -0,0 +1,106 @@
|
||||
<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'/>
|
||||
<controller type='pci' index='0' model='pci-root'/>
|
||||
<controller type='scsi' index='1'/>
|
||||
<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='0' unit='0'/>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host1'/>
|
||||
<address bus='0' target='0' unit='1'/>
|
||||
</source>
|
||||
<address type='drive' controller='0' bus='0' target='0' unit='1'/>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host2'/>
|
||||
<address bus='0' target='0' unit='2'/>
|
||||
</source>
|
||||
<address type='drive' controller='0' bus='0' target='0' unit='2'/>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host3'/>
|
||||
<address bus='0' target='0' unit='3'/>
|
||||
</source>
|
||||
<address type='drive' controller='0' bus='0' target='0' unit='3'/>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host4'/>
|
||||
<address bus='0' target='0' unit='4'/>
|
||||
</source>
|
||||
<address type='drive' controller='0' bus='0' target='0' unit='4'/>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host5'/>
|
||||
<address bus='0' target='0' unit='5'/>
|
||||
</source>
|
||||
<address type='drive' controller='0' bus='0' target='0' unit='5'/>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host6'/>
|
||||
<address bus='0' target='0' unit='6'/>
|
||||
</source>
|
||||
<address type='drive' controller='0' bus='0' target='0' unit='6'/>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host7'/>
|
||||
<address bus='0' target='0' unit='7'/>
|
||||
</source>
|
||||
<address type='drive' controller='1' bus='0' target='0' unit='0'/>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host8'/>
|
||||
<address bus='0' target='0' unit='8'/>
|
||||
</source>
|
||||
<address type='drive' controller='1' bus='0' target='0' unit='1'/>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host9'/>
|
||||
<address bus='0' target='0' unit='9'/>
|
||||
</source>
|
||||
<address type='drive' controller='1' bus='0' target='0' unit='5'/>
|
||||
</hostdev>
|
||||
<hostdev mode='subsystem' type='scsi' managed='yes'>
|
||||
<source>
|
||||
<adapter name='scsi_host10'/>
|
||||
<address bus='0' target='0' unit='10'/>
|
||||
</source>
|
||||
<address type='drive' controller='1' bus='0' target='0' unit='2'/>
|
||||
</hostdev>
|
||||
<memballoon model='virtio'/>
|
||||
</devices>
|
||||
</domain>
|
@ -298,6 +298,8 @@ mymain(void)
|
||||
DO_TEST("hostdev-scsi-shareable");
|
||||
DO_TEST("hostdev-scsi-sgio");
|
||||
|
||||
DO_TEST_DIFFERENT("hostdev-scsi-autogen-address");
|
||||
|
||||
virObjectUnref(driver.caps);
|
||||
virObjectUnref(driver.xmlopt);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user