diff options
Diffstat (limited to 'src/main')
| -rw-r--r-- | src/main/java/org/openslx/libvirt/domain/DomainUtils.java | 78 |
1 files changed, 77 insertions, 1 deletions
diff --git a/src/main/java/org/openslx/libvirt/domain/DomainUtils.java b/src/main/java/org/openslx/libvirt/domain/DomainUtils.java index 2462371..34dcdd6 100644 --- a/src/main/java/org/openslx/libvirt/domain/DomainUtils.java +++ b/src/main/java/org/openslx/libvirt/domain/DomainUtils.java @@ -2,9 +2,11 @@ package org.openslx.libvirt.domain; import java.math.BigInteger; +import org.openslx.libvirt.domain.device.HostdevPciDeviceAddress; + /** * Collection of helper functions to maintain a Libvirt domain XML document. - * + * * @author Manuel Bentele * @version 1.0 */ @@ -115,4 +117,78 @@ public final class DomainUtils return value.divide( dividend ).toString(); } + + /** + * Builds a PCI slot usage map from all devices in the given domain configuration. + * <p> + * The returned array tracks which PCI device slots are in use on the primary bus + * (domain 0, bus 0). Array indices correspond to device numbers (0-63), with: + * </p> + * <ul> + * <li>{@code 0} = slot is free</li> + * <li>{@code >0} = slot is occupied (value encodes domain:bus:device lookup)</li> + * </ul> + * <p> + * Slots 0 and 1 are pre-marked as reserved. + * </p> + * + * @param config domain configuration to scan for existing PCI devices + * @return array of size 64 tracking PCI slot usage + */ + public static int[] buildPciSlotUsageMap( Domain config ) + { + int[] inUse = new int[ 64 ]; + inUse[ 0 ] = Integer.MAX_VALUE; + inUse[ 1 ] = Integer.MAX_VALUE; + + for ( org.openslx.libvirt.domain.device.Device dev : config.getDevices() ) { + HostdevPciDeviceAddress target = dev.getPciTarget(); + if ( target == null ) + continue; + if ( target.getPciDomain() != 0 || target.getPciBus() != 0 ) + continue; // Ignore non-primary bus + if ( target.getPciDevice() >= inUse.length ) + continue; + inUse[ target.getPciDevice() ] = Integer.MAX_VALUE; + } + + return inUse; + } + + /** + * Finds a free PCI device slot on the primary bus (domain 0, bus 0) that doesn't + * collide with existing device addresses. + * <p> + * The method first checks if the exact same PCI address was already assigned + * (for reuse), otherwise returns the first free slot starting from device 2. + * </p> + * + * @param inUse PCI slot usage map from {@link #buildPciSlotUsageMap(Domain)} + * @param pciDeviceAddress original PCI device address to find a slot for + * @return free PCI device number (0-63) for assignment + * @throws IllegalStateException if no free PCI slot is available + */ + public static int findFreePciDeviceSlot( int[] inUse, HostdevPciDeviceAddress pciDeviceAddress ) + { + int devAddr; + int firstFree = -1; + int lookup = ( pciDeviceAddress.getPciDomain() << 16 ) + | ( pciDeviceAddress.getPciBus() << 8 ) + | ( pciDeviceAddress.getPciDevice() ); + + for ( devAddr = 0; devAddr < inUse.length; ++devAddr ) { + if ( firstFree == -1 && inUse[ devAddr ] == 0 ) { + firstFree = devAddr; + } else if ( inUse[ devAddr ] == lookup ) { + return devAddr; + } + } + + if ( firstFree == -1 ) { + throw new IllegalStateException( "No free PCI device slot available" ); + } + + inUse[ firstFree ] = lookup; + return firstFree; + } } |
