Beispiel #1
0
/*
 * 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;
}
Beispiel #2
0
/* 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;
}
Beispiel #3
0
/* 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;
}