diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 21685e1ca0..098e49c143 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -1341,39 +1341,82 @@ cleanup: } int -qemuSetUnprivSGIO(virDomainDiskDefPtr disk) +qemuSetUnprivSGIO(virDomainDeviceDefPtr dev) { + virDomainDiskDefPtr disk = NULL; + virDomainHostdevDefPtr hostdev = NULL; char *sysfs_path = NULL; + char *path = NULL; + char *hostdev_name = NULL; + char *hostdev_path = NULL; int val = -1; int ret = 0; /* "sgio" is only valid for block disk; cdrom * and floopy disk can have empty source. */ - if (!disk->src || - disk->device != VIR_DOMAIN_DISK_DEVICE_LUN || - (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK && - !(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME && - disk->srcpool && - disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK))) - return 0; + if (dev->type == VIR_DOMAIN_DEVICE_DISK) { + disk = dev->data.disk; - sysfs_path = virGetUnprivSGIOSysfsPath(disk->src, NULL); - if (sysfs_path == NULL) - return -1; + if (!disk->src || + disk->device != VIR_DOMAIN_DISK_DEVICE_LUN || + (disk->type != VIR_DOMAIN_DISK_TYPE_BLOCK && + !(disk->type == VIR_DOMAIN_DISK_TYPE_VOLUME && + disk->srcpool && + disk->srcpool->voltype == VIR_STORAGE_VOL_BLOCK))) + return 0; + + path = disk->src; + } else if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV) { + hostdev = dev->data.hostdev; + + if (!hostdev->shareable || + !(hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && + hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)) + return 0; + + 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) { + virReportOOMError(); + goto cleanup; + } + + path = hostdev_path; + } else { + return 0; + } + + sysfs_path = virGetUnprivSGIOSysfsPath(path, NULL); + if (sysfs_path == NULL) { + ret = -1; + goto cleanup; + } /* By default, filter the SG_IO commands, i.e. set unpriv_sgio to 0. */ - val = (disk->sgio == VIR_DOMAIN_DEVICE_SGIO_UNFILTERED); + + if (dev->type == VIR_DOMAIN_DEVICE_DISK) + val = (disk->sgio == VIR_DOMAIN_DEVICE_SGIO_UNFILTERED); + else + val = (hostdev->source.subsys.u.scsi.sgio == + VIR_DOMAIN_DEVICE_SGIO_UNFILTERED); /* Do not do anything if unpriv_sgio is not supported by the kernel and the * whitelist is enabled. But if requesting unfiltered access, always call * virSetDeviceUnprivSGIO, to report an error for unsupported unpriv_sgio. */ if ((virFileExists(sysfs_path) || val == 1) && - virSetDeviceUnprivSGIO(disk->src, NULL, val) < 0) + virSetDeviceUnprivSGIO(path, NULL, val) < 0) ret = -1; +cleanup: VIR_FREE(sysfs_path); + VIR_FREE(hostdev_name); + VIR_FREE(hostdev_path); return ret; } diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 25350ddec5..df0791ec04 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -305,7 +305,7 @@ int qemuRemoveSharedDevice(virQEMUDriverPtr driver, const char *name) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3); -int qemuSetUnprivSGIO(virDomainDiskDefPtr disk); +int qemuSetUnprivSGIO(virDomainDeviceDefPtr dev); int qemuDriverAllocateID(virQEMUDriverPtr driver); virDomainXMLOptionPtr virQEMUDriverCreateXMLConf(virQEMUDriverPtr driver); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d1708cea77..1933c8f269 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -5734,7 +5734,7 @@ qemuDomainAttachDeviceDiskLive(virConnectPtr conn, if (qemuAddSharedDevice(driver, dev, vm->def->name) < 0) goto end; - if (qemuSetUnprivSGIO(disk) < 0) + if (qemuSetUnprivSGIO(dev) < 0) goto end; if (qemuDomainDetermineDiskChain(driver, disk, false) < 0) diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index c25769da59..4a7c6127d5 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -3669,7 +3669,7 @@ int qemuProcessStart(virConnectPtr conn, if (qemuAddSharedDevice(driver, &dev, vm->def->name) < 0) goto cleanup; - if (qemuSetUnprivSGIO(disk) < 0) + if (qemuSetUnprivSGIO(&dev) < 0) goto cleanup; }