/* * Make necessary checks for the need to check and for the current setting * of the 'unpriv_sgio' value for the device_path passed. * * Returns: * 0 - Success * -1 - Some failure which would already have been messaged * -2 - Mismatch with the "shared" sgio setting - needs to be messaged * by caller since it has context of which type of disk resource is * being used and in the future the hostdev information. */ static int qemuCheckUnprivSGIO(virHashTablePtr sharedDevices, const char *device_path, int sgio) { char *sysfs_path = NULL; char *key = NULL; int val; int ret = -1; if (!(sysfs_path = virGetUnprivSGIOSysfsPath(device_path, NULL))) goto cleanup; /* It can't be conflict if unpriv_sgio is not supported by kernel. */ if (!virFileExists(sysfs_path)) { ret = 0; goto cleanup; } if (!(key = qemuGetSharedDeviceKey(device_path))) goto cleanup; /* It can't be conflict if no other domain is sharing it. */ if (!(virHashLookup(sharedDevices, key))) { ret = 0; goto cleanup; } if (virGetDeviceUnprivSGIO(device_path, NULL, &val) < 0) goto cleanup; /* Error message on failure needs to be handled in caller * since there is more specific knowledge of device */ if (!((val == 0 && (sgio == VIR_DOMAIN_DEVICE_SGIO_FILTERED || sgio == VIR_DOMAIN_DEVICE_SGIO_DEFAULT)) || (val == 1 && sgio == VIR_DOMAIN_DEVICE_SGIO_UNFILTERED))) { ret = -2; goto cleanup; } ret = 0; cleanup: VIR_FREE(sysfs_path); VIR_FREE(key); return ret; }
/* Check if a shared device's setting conflicts with the conf * used by other domain(s). Currently only checks the sgio * setting. Note that this should only be called for disk with * block source if the device type is disk. * * Returns 0 if no conflicts, otherwise returns -1. */ static int qemuCheckSharedDevice(virHashTablePtr sharedDevices, virDomainDeviceDefPtr dev) { virDomainDiskDefPtr disk = NULL; char *sysfs_path = NULL; char *key = NULL; int val; int ret = 0; if (dev->type == VIR_DOMAIN_DEVICE_DISK) { disk = dev->data.disk; /* The only conflicts between shared disk we care about now * is sgio setting, which is only valid for device='lun'. */ if (disk->device != VIR_DOMAIN_DISK_DEVICE_LUN) return 0; } else { return 0; } if (!(sysfs_path = virGetUnprivSGIOSysfsPath(disk->src, NULL))) { ret = -1; goto cleanup; } /* It can't be conflict if unpriv_sgio is not supported * by kernel. */ if (!virFileExists(sysfs_path)) goto cleanup; if (!(key = qemuGetSharedDeviceKey(disk->src))) { ret = -1; goto cleanup; } /* It can't be conflict if no other domain is * is sharing it. */ if (!(virHashLookup(sharedDevices, key))) goto cleanup; if (virGetDeviceUnprivSGIO(disk->src, NULL, &val) < 0) { ret = -1; goto cleanup; } if ((val == 0 && (disk->sgio == VIR_DOMAIN_DEVICE_SGIO_FILTERED || disk->sgio == VIR_DOMAIN_DEVICE_SGIO_DEFAULT)) || (val == 1 && disk->sgio == VIR_DOMAIN_DEVICE_SGIO_UNFILTERED)) goto cleanup; if (disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME) { virReportError(VIR_ERR_OPERATION_INVALID, _("sgio of shared disk 'pool=%s' 'volume=%s' conflicts " "with other active domains"), disk->srcpool->pool, disk->srcpool->volume); } else { virReportError(VIR_ERR_OPERATION_INVALID, _("sgio of shared disk '%s' conflicts with other " "active domains"), disk->src); } ret = -1; cleanup: VIR_FREE(sysfs_path); VIR_FREE(key); return ret; }
/* Check if a shared device's setting conflicts with the conf * used by other domain(s). Currently only checks the sgio * setting. Note that this should only be called for disk with * block source if the device type is disk. * * Returns 0 if no conflicts, otherwise returns -1. */ static int qemuCheckSharedDevice(virHashTablePtr sharedDevices, virDomainDeviceDefPtr dev) { virDomainDiskDefPtr disk = NULL; virDomainHostdevDefPtr hostdev = NULL; char *sysfs_path = NULL; char *key = NULL; char *hostdev_name = NULL; char *hostdev_path = NULL; char *device_path = NULL; int val; int ret = 0; if (dev->type == VIR_DOMAIN_DEVICE_DISK) { disk = dev->data.disk; /* The only conflicts between shared disk we care about now * is sgio setting, which is only valid for device='lun'. */ if (disk->device != VIR_DOMAIN_DISK_DEVICE_LUN) return 0; device_path = disk->src; } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { hostdev = dev->data.hostdev; if (!(hostdev_name = virSCSIDeviceGetDevName(hostdev->source.subsys.u.scsi.adapter, hostdev->source.subsys.u.scsi.bus, hostdev->source.subsys.u.scsi.target, hostdev->source.subsys.u.scsi.unit))) goto cleanup; if (virAsprintf(&hostdev_path, "/dev/%s", hostdev_name) < 0) goto cleanup; device_path = hostdev_path; } else { return 0; } if (!(sysfs_path = virGetUnprivSGIOSysfsPath(device_path, NULL))) { ret = -1; goto cleanup; } /* It can't be conflict if unpriv_sgio is not supported * by kernel. */ if (!virFileExists(sysfs_path)) goto cleanup; if (!(key = qemuGetSharedDeviceKey(device_path))) { ret = -1; goto cleanup; } /* It can't be conflict if no other domain is * is sharing it. */ if (!(virHashLookup(sharedDevices, key))) goto cleanup; if (virGetDeviceUnprivSGIO(device_path, NULL, &val) < 0) { ret = -1; goto cleanup; } if ((val == 0 && (disk->sgio == VIR_DOMAIN_DEVICE_SGIO_FILTERED || disk->sgio == VIR_DOMAIN_DEVICE_SGIO_DEFAULT)) || (val == 1 && disk->sgio == VIR_DOMAIN_DEVICE_SGIO_UNFILTERED)) goto cleanup; if (dev->type == VIR_DOMAIN_DEVICE_DISK) { if (disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME) { virReportError(VIR_ERR_OPERATION_INVALID, _("sgio of shared disk 'pool=%s' 'volume=%s' conflicts " "with other active domains"), disk->srcpool->pool, disk->srcpool->volume); } else { virReportError(VIR_ERR_OPERATION_INVALID, _("sgio of shared disk '%s' conflicts with other " "active domains"), disk->src); } } else { virReportError(VIR_ERR_OPERATION_INVALID, _("sgio of shared scsi host device '%s-%d-%d-%d' conflicts " "with other active domains"), hostdev->source.subsys.u.scsi.adapter, hostdev->source.subsys.u.scsi.bus, hostdev->source.subsys.u.scsi.target, hostdev->source.subsys.u.scsi.unit); } ret = -1; cleanup: VIR_FREE(hostdev_name); VIR_FREE(hostdev_path); VIR_FREE(sysfs_path); VIR_FREE(key); return ret; }