hostdev: Introduce virDomainHostdevSubsysSCSIiSCSI

Create the structures and API's to hold and manage the iSCSI host device.
This extends the 'scsi_host' definitions added in commit id '5c811dce'.
A future patch will add the XML parsing, but that code requires some
infrastructure to be in place first in order to handle the differences
between a 'scsi_host' and an 'iSCSI host' device.
This commit is contained in:
John Ferlan 2014-07-09 09:31:38 -04:00
parent a062d1a1cc
commit 17bddc46f4
10 changed files with 349 additions and 113 deletions

View File

@ -424,12 +424,22 @@ virDomainAuditHostdev(virDomainObjPtr vm, virDomainHostdevDefPtr hostdev,
}
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
if (virAsprintfQuiet(&address, "%s:%d:%d:%d",
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit) < 0) {
VIR_WARN("OOM while encoding audit message");
if (scsisrc->protocol ==
VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
/* Follow virDomainAuditDisk && virDomainAuditGenericDev
* and don't audit the networked device.
*/
goto cleanup;
} else {
virDomainHostdevSubsysSCSIHostPtr scsihostsrc =
&scsisrc->u.host;
if (virAsprintfQuiet(&address, "%s:%d:%d:%d",
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target,
scsihostsrc->unit) < 0) {
VIR_WARN("OOM while encoding audit message");
goto cleanup;
}
}
break;
}

View File

@ -1695,6 +1695,17 @@ virDomainHostdevDefPtr virDomainHostdevDefAlloc(void)
return def;
}
static void
virDomainHostdevSubsysSCSIiSCSIClear(virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc)
{
if (!iscsisrc)
return;
VIR_FREE(iscsisrc->path);
virStorageNetHostDefFree(iscsisrc->nhosts, iscsisrc->hosts);
virStorageAuthDefFree(iscsisrc->auth);
iscsisrc->auth = NULL;
}
void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
{
if (!def)
@ -1725,8 +1736,15 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
}
break;
case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)
VIR_FREE(def->source.subsys.u.scsi.u.host.adapter);
if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
virDomainHostdevSubsysSCSIPtr scsisrc = &def->source.subsys.u.scsi;
if (scsisrc->protocol ==
VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
virDomainHostdevSubsysSCSIiSCSIClear(&scsisrc->u.iscsi);
} else {
VIR_FREE(scsisrc->u.host.adapter);
}
}
break;
}
}
@ -4306,8 +4324,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
}
if (sgio) {
if (def->source.subsys.type !=
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
if (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("sgio is only supported for scsi host device"));
goto error;
@ -10255,6 +10272,22 @@ virDomainHostdevMatchSubsysSCSIHost(virDomainHostdevDefPtr first,
return 0;
}
static int
virDomainHostdevMatchSubsysSCSIiSCSI(virDomainHostdevDefPtr first,
virDomainHostdevDefPtr second)
{
virDomainHostdevSubsysSCSIiSCSIPtr first_iscsisrc =
&first->source.subsys.u.scsi.u.iscsi;
virDomainHostdevSubsysSCSIiSCSIPtr second_iscsisrc =
&second->source.subsys.u.scsi.u.iscsi;
if (STREQ(first_iscsisrc->hosts[0].name, second_iscsisrc->hosts[0].name) &&
STREQ(first_iscsisrc->hosts[0].port, second_iscsisrc->hosts[0].port) &&
STREQ(first_iscsisrc->path, second_iscsisrc->path))
return 1;
return 0;
}
static int
virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a,
virDomainHostdevDefPtr b)
@ -10268,7 +10301,11 @@ virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a,
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
return virDomainHostdevMatchSubsysUSB(a, b);
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
return virDomainHostdevMatchSubsysSCSIHost(a, b);
if (a->source.subsys.u.scsi.protocol ==
VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
return virDomainHostdevMatchSubsysSCSIiSCSI(a, b);
else
return virDomainHostdevMatchSubsysSCSIHost(a, b);
}
return 0;
}

View File

@ -388,6 +388,15 @@ typedef enum {
VIR_ENUM_DECL(virDomainHostdevSubsysPCIBackend)
typedef enum {
VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_NONE,
VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI,
VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_LAST,
} virDomainHostdevSCSIProtocolType;
VIR_ENUM_DECL(virDomainHostdevSubsysSCSIProtocol)
typedef struct _virDomainHostdevSubsysUSB virDomainHostdevSubsysUSB;
typedef virDomainHostdevSubsysUSB *virDomainHostdevSubsysUSBPtr;
struct _virDomainHostdevSubsysUSB {
@ -416,12 +425,23 @@ struct _virDomainHostdevSubsysSCSIHost {
unsigned unit;
};
typedef struct _virDomainHostdevSubsysSCSIiSCSI virDomainHostdevSubsysSCSIiSCSI;
typedef virDomainHostdevSubsysSCSIiSCSI *virDomainHostdevSubsysSCSIiSCSIPtr;
struct _virDomainHostdevSubsysSCSIiSCSI {
char *path;
size_t nhosts;
virStorageNetHostDefPtr hosts;
virStorageAuthDefPtr auth;
};
typedef struct _virDomainHostdevSubsysSCSI virDomainHostdevSubsysSCSI;
typedef virDomainHostdevSubsysSCSI *virDomainHostdevSubsysSCSIPtr;
struct _virDomainHostdevSubsysSCSI {
int protocol; /* enum virDomainHostdevSCSIProtocolType */
int sgio; /* enum virDomainDeviceSGIO */
union {
virDomainHostdevSubsysSCSIHost host;
virDomainHostdevSubsysSCSIiSCSI iscsi;
} u;
};

View File

@ -307,18 +307,31 @@ qemuSetupHostdevCGroup(virDomainObjPtr vm,
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
if ((scsi = virSCSIDeviceNew(NULL,
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit,
dev->readonly,
dev->shareable)) == NULL)
goto cleanup;
if (scsisrc->protocol ==
VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
/* Follow qemuSetupDiskCgroup() and qemuSetImageCgroupInternal()
* which does nothing for non local storage
*/
VIR_DEBUG("Not updating cgroups for hostdev iSCSI path '%s'",
iscsisrc->path);
} else {
virDomainHostdevSubsysSCSIHostPtr scsihostsrc =
&scsisrc->u.host;
if ((scsi = virSCSIDeviceNew(NULL,
scsihostsrc->adapter,
scsihostsrc->bus,
scsihostsrc->target,
scsihostsrc->unit,
dev->readonly,
dev->shareable)) == NULL)
goto cleanup;
if (virSCSIDeviceFileIterate(scsi,
qemuSetupHostSCSIDeviceCgroup,
vm) < 0)
goto cleanup;
if (virSCSIDeviceFileIterate(scsi,
qemuSetupHostSCSIDeviceCgroup,
vm) < 0)
goto cleanup;
}
break;
}

View File

@ -5124,13 +5124,11 @@ qemuBuildUSBHostdevUSBDevStr(virDomainHostdevDefPtr dev)
return ret;
}
char *
qemuBuildSCSIHostdevDrvStr(virConnectPtr conn ATTRIBUTE_UNUSED,
virDomainHostdevDefPtr dev,
virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED,
qemuBuildCommandLineCallbacksPtr callbacks)
static char *
qemuBuildSCSIHostHostdevDrvStr(virDomainHostdevDefPtr dev,
virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED,
qemuBuildCommandLineCallbacksPtr callbacks)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
char *sg = NULL;
@ -5140,10 +5138,64 @@ qemuBuildSCSIHostdevDrvStr(virConnectPtr conn ATTRIBUTE_UNUSED,
scsihostsrc->bus,
scsihostsrc->target,
scsihostsrc->unit);
if (!sg)
goto error;
return sg;
}
virBufferAsprintf(&buf, "file=/dev/%s,if=none", sg);
static char *
qemuBuildSCSIiSCSIHostdevDrvStr(virConnectPtr conn,
virDomainHostdevDefPtr dev)
{
char *source = NULL;
char *secret = NULL;
char *username = NULL;
virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
if (conn && iscsisrc->auth) {
const char *protocol =
virStorageNetProtocolTypeToString(VIR_STORAGE_NET_PROTOCOL_ISCSI);
bool encode = false;
int secretType = VIR_SECRET_USAGE_TYPE_ISCSI;
username = iscsisrc->auth->username;
if (!(secret = qemuGetSecretString(conn, protocol, encode,
iscsisrc->auth, secretType)))
goto cleanup;
}
/* Rather than pull what we think we want - use the network disk code */
source = qemuBuildNetworkDriveURI(VIR_STORAGE_NET_PROTOCOL_ISCSI,
iscsisrc->path,
NULL, /* volume */
iscsisrc->nhosts,
iscsisrc->hosts,
username, secret);
cleanup:
VIR_FREE(secret);
return source;
}
char *
qemuBuildSCSIHostdevDrvStr(virConnectPtr conn,
virDomainHostdevDefPtr dev,
virQEMUCapsPtr qemuCaps,
qemuBuildCommandLineCallbacksPtr callbacks)
{
virBuffer buf = VIR_BUFFER_INITIALIZER;
char *source = NULL;
virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
if (!(source = qemuBuildSCSIiSCSIHostdevDrvStr(conn, dev)))
goto error;
virBufferAsprintf(&buf, "file=%s,if=none,format=raw", source);
} else {
if (!(source = qemuBuildSCSIHostHostdevDrvStr(dev, qemuCaps,
callbacks)))
goto error;
virBufferAsprintf(&buf, "file=/dev/%s,if=none", source);
}
virBufferAsprintf(&buf, ",id=%s-%s",
virDomainDeviceAddressTypeToString(dev->info->type),
dev->info->alias);
@ -5162,10 +5214,10 @@ qemuBuildSCSIHostdevDrvStr(virConnectPtr conn ATTRIBUTE_UNUSED,
if (virBufferCheckError(&buf) < 0)
goto error;
VIR_FREE(sg);
VIR_FREE(source);
return virBufferContentAndReset(&buf);
error:
VIR_FREE(sg);
VIR_FREE(source);
virBufferFreeAndReset(&buf);
return NULL;
}

View File

@ -1575,11 +1575,18 @@ qemuDomainAttachHostSCSIDevice(virConnectPtr conn,
if (qemuPrepareHostdevSCSIDevices(driver, vm->def->name,
&hostdev, 1)) {
virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi;
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to prepare scsi hostdev: %s:%d:%d:%d"),
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit);
if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to prepare scsi hostdev for iSCSI: %s"),
iscsisrc->path);
} else {
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unable to prepare scsi hostdev: %s:%d:%d:%d"),
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit);
}
return -1;
}
@ -3400,11 +3407,20 @@ int qemuDomainDetachHostDevice(virConnectPtr conn,
}
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
virReportError(VIR_ERR_OPERATION_FAILED,
_("host scsi device %s:%d:%d.%d not found"),
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit);
if (scsisrc->protocol ==
VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
virReportError(VIR_ERR_OPERATION_FAILED,
_("host scsi iSCSI path %s not found"),
iscsisrc->path);
} else {
virDomainHostdevSubsysSCSIHostPtr scsihostsrc =
&scsisrc->u.host;
virReportError(VIR_ERR_OPERATION_FAILED,
_("host scsi device %s:%d:%d.%d not found"),
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit);
}
break;
}
default:

View File

@ -825,6 +825,12 @@ AppArmorSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
return 0;
/* Like AppArmorRestoreSecurityImageLabel() for a networked disk,
* do nothing for an iSCSI hostdev
*/
if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
return 0;
if (profile_loaded(secdef->imagelabel) < 0)
return 0;

View File

@ -520,6 +520,12 @@ virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
return 0;
/* Like virSecurityDACSetSecurityImageLabel() for a networked disk,
* do nothing for an iSCSI hostdev
*/
if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
return 0;
cbdata.manager = mgr;
cbdata.secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
@ -648,6 +654,12 @@ virSecurityDACRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
return 0;
/* Like virSecurityDACRestoreSecurityImageLabelInt() for a networked disk,
* do nothing for an iSCSI hostdev
*/
if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
return 0;
switch ((virDomainHostdevSubsysType) dev->source.subsys.type) {
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
virUSBDevicePtr usb;

View File

@ -1324,6 +1324,12 @@ virSecuritySELinuxSetSecurityHostdevSubsysLabel(virDomainDefPtr def,
virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
int ret = -1;
/* Like virSecuritySELinuxSetSecurityImageLabelInternal() for a networked
* disk, do nothing for an iSCSI hostdev
*/
if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
return 0;
switch (dev->source.subsys.type) {
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
virUSBDevicePtr usb;
@ -1511,6 +1517,12 @@ virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(virSecurityManagerPtr mgr,
virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
int ret = -1;
/* Like virSecuritySELinuxRestoreSecurityImageLabelInt() for a networked
* disk, do nothing for an iSCSI hostdev
*/
if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
return 0;
switch (dev->source.subsys.type) {
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
virUSBDevicePtr usb;

View File

@ -920,6 +920,43 @@ virHostdevUpdateActiveUSBDevices(virHostdevManagerPtr mgr,
return ret;
}
static int
virHostdevUpdateActiveSCSIHostDevices(virHostdevManagerPtr mgr,
virDomainHostdevDefPtr hostdev,
virDomainHostdevSubsysSCSIPtr scsisrc,
const char *drv_name,
const char *dom_name)
{
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
virSCSIDevicePtr scsi = NULL;
virSCSIDevicePtr tmp = NULL;
int ret = -1;
if (!(scsi = virSCSIDeviceNew(NULL,
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit,
hostdev->readonly, hostdev->shareable)))
goto cleanup;
if ((tmp = virSCSIDeviceListFind(mgr->activeSCSIHostdevs, scsi))) {
if (virSCSIDeviceSetUsedBy(tmp, drv_name, dom_name) < 0) {
virSCSIDeviceFree(scsi);
goto cleanup;
}
virSCSIDeviceFree(scsi);
} else {
if (virSCSIDeviceSetUsedBy(scsi, drv_name, dom_name) < 0 ||
virSCSIDeviceListAdd(mgr->activeSCSIHostdevs, scsi) < 0) {
virSCSIDeviceFree(scsi);
goto cleanup;
}
}
ret = 0;
cleanup:
return ret;
}
int
virHostdevUpdateActiveSCSIDevices(virHostdevManagerPtr mgr,
virDomainHostdevDefPtr *hostdevs,
@ -930,40 +967,26 @@ virHostdevUpdateActiveSCSIDevices(virHostdevManagerPtr mgr,
virDomainHostdevDefPtr hostdev = NULL;
size_t i;
int ret = -1;
virSCSIDevicePtr scsi = NULL;
virSCSIDevicePtr tmp = NULL;
if (!nhostdevs)
return 0;
virObjectLock(mgr->activeSCSIHostdevs);
for (i = 0; i < nhostdevs; i++) {
virDomainHostdevSubsysSCSIHostPtr scsihostsrc;
virDomainHostdevSubsysSCSIPtr scsisrc;
hostdev = hostdevs[i];
scsihostsrc = &hostdev->source.subsys.u.scsi.u.host;
scsisrc = &hostdev->source.subsys.u.scsi;
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)
continue;
if (!(scsi = virSCSIDeviceNew(NULL,
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit,
hostdev->readonly, hostdev->shareable)))
goto cleanup;
if ((tmp = virSCSIDeviceListFind(mgr->activeSCSIHostdevs, scsi))) {
if (virSCSIDeviceSetUsedBy(tmp, drv_name, dom_name) < 0) {
virSCSIDeviceFree(scsi);
goto cleanup;
}
virSCSIDeviceFree(scsi);
if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
continue; /* Not supported for iSCSI */
} else {
if (virSCSIDeviceSetUsedBy(scsi, drv_name, dom_name) < 0 ||
virSCSIDeviceListAdd(mgr->activeSCSIHostdevs, scsi) < 0) {
virSCSIDeviceFree(scsi);
if (virHostdevUpdateActiveSCSIHostDevices(mgr, hostdev, scsisrc,
drv_name, dom_name) < 0)
goto cleanup;
}
}
}
ret = 0;
@ -1193,6 +1216,38 @@ virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr,
return ret;
}
static int
virHostdevPrepareSCSIHostDevices(virDomainHostdevDefPtr hostdev,
virDomainHostdevSubsysSCSIPtr scsisrc,
virSCSIDeviceListPtr list)
{
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
virSCSIDevicePtr scsi;
int ret = -1;
if (hostdev->managed) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("SCSI host device doesn't support managed mode"));
goto cleanup;
}
if (!(scsi = virSCSIDeviceNew(NULL,
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit,
hostdev->readonly, hostdev->shareable)))
goto cleanup;
if (virSCSIDeviceListAdd(list, scsi) < 0) {
virSCSIDeviceFree(scsi);
goto cleanup;
}
ret = 0;
cleanup:
return ret;
}
int
virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr,
const char *drv_name,
@ -1219,29 +1274,17 @@ virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr,
/* Loop 1: build temporary list */
for (i = 0; i < nhostdevs; i++) {
virDomainHostdevDefPtr hostdev = hostdevs[i];
virDomainHostdevSubsysSCSIHostPtr scsihostsrc =
&hostdev->source.subsys.u.scsi.u.host;
virSCSIDevicePtr scsi;
virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi;
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)
continue;
if (hostdev->managed) {
virReportError(VIR_ERR_XML_ERROR, "%s",
_("SCSI host device doesn't support managed mode"));
goto cleanup;
}
if (!(scsi = virSCSIDeviceNew(NULL,
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit,
hostdev->readonly, hostdev->shareable)))
goto cleanup;
if (scsi && virSCSIDeviceListAdd(list, scsi) < 0) {
virSCSIDeviceFree(scsi);
goto cleanup;
if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
continue; /* Not supported for iSCSI */
} else {
if (virHostdevPrepareSCSIHostDevices(hostdev, scsisrc, list) < 0)
goto cleanup;
}
}
@ -1366,6 +1409,48 @@ virHostdevReAttachUSBDevices(virHostdevManagerPtr hostdev_mgr,
virObjectUnlock(hostdev_mgr->activeUSBHostdevs);
}
static void
virHostdevReAttachSCSIHostDevices(virHostdevManagerPtr hostdev_mgr,
virDomainHostdevDefPtr hostdev,
virDomainHostdevSubsysSCSIPtr scsisrc,
const char *drv_name,
const char *dom_name)
{
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
virSCSIDevicePtr scsi;
virSCSIDevicePtr tmp;
if (!(scsi = virSCSIDeviceNew(NULL,
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit,
hostdev->readonly, hostdev->shareable))) {
VIR_WARN("Unable to reattach SCSI device %s:%d:%d:%d on domain %s",
scsihostsrc->adapter, scsihostsrc->bus, scsihostsrc->target,
scsihostsrc->unit, dom_name);
return;
}
/* Only delete the devices which are marked as being used by @name,
* because qemuProcessStart could fail half way through. */
if (!(tmp = virSCSIDeviceListFind(hostdev_mgr->activeSCSIHostdevs, scsi))) {
VIR_WARN("Unable to find device %s:%d:%d:%d "
"in list of active SCSI devices",
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit);
virSCSIDeviceFree(scsi);
return;
}
VIR_DEBUG("Removing %s:%d:%d:%d dom=%s from activeSCSIHostdevs",
scsihostsrc->adapter, scsihostsrc->bus, scsihostsrc->target,
scsihostsrc->unit, dom_name);
virSCSIDeviceListDel(hostdev_mgr->activeSCSIHostdevs, tmp,
drv_name, dom_name);
virSCSIDeviceFree(scsi);
}
void
virHostdevReAttachSCSIDevices(virHostdevManagerPtr hostdev_mgr,
const char *drv_name,
@ -1381,44 +1466,17 @@ virHostdevReAttachSCSIDevices(virHostdevManagerPtr hostdev_mgr,
virObjectLock(hostdev_mgr->activeSCSIHostdevs);
for (i = 0; i < nhostdevs; i++) {
virDomainHostdevDefPtr hostdev = hostdevs[i];
virDomainHostdevSubsysSCSIHostPtr scsihostsrc =
&hostdev->source.subsys.u.scsi.u.host;
virSCSIDevicePtr scsi;
virSCSIDevicePtr tmp;
virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi;
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)
continue;
if (!(scsi = virSCSIDeviceNew(NULL,
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit,
hostdev->readonly, hostdev->shareable))) {
VIR_WARN("Unable to reattach SCSI device %s:%d:%d:%d on domain %s",
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit, dom_name);
continue;
}
/* Only delete the devices which are marked as being used by @name,
* because qemuProcessStart could fail on the half way. */
if (!(tmp = virSCSIDeviceListFind(hostdev_mgr->activeSCSIHostdevs, scsi))) {
VIR_WARN("Unable to find device %s:%d:%d:%d "
"in list of active SCSI devices",
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit);
virSCSIDeviceFree(scsi);
continue;
}
VIR_DEBUG("Removing %s:%d:%d:%d dom=%s from activeSCSIHostdevs",
scsihostsrc->adapter, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->unit, dom_name);
virSCSIDeviceListDel(hostdev_mgr->activeSCSIHostdevs, tmp,
drv_name, dom_name);
virSCSIDeviceFree(scsi);
if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
continue; /* Not supported for iSCSI */
else
virHostdevReAttachSCSIHostDevices(hostdev_mgr, hostdev, scsisrc,
drv_name, dom_name);
}
virObjectUnlock(hostdev_mgr->activeSCSIHostdevs);
}