1
0

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; break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; if (scsisrc->protocol ==
if (virAsprintfQuiet(&address, "%s:%d:%d:%d", VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
scsihostsrc->adapter, scsihostsrc->bus, /* Follow virDomainAuditDisk && virDomainAuditGenericDev
scsihostsrc->target, scsihostsrc->unit) < 0) { * and don't audit the networked device.
VIR_WARN("OOM while encoding audit message"); */
goto cleanup; 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; break;
} }

View File

@ -1695,6 +1695,17 @@ virDomainHostdevDefPtr virDomainHostdevDefAlloc(void)
return def; 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) void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
{ {
if (!def) if (!def)
@ -1725,8 +1736,15 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
} }
break; break;
case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
VIR_FREE(def->source.subsys.u.scsi.u.host.adapter); 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; break;
} }
} }
@ -4306,8 +4324,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
} }
if (sgio) { if (sgio) {
if (def->source.subsys.type != if (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) {
virReportError(VIR_ERR_XML_ERROR, "%s", virReportError(VIR_ERR_XML_ERROR, "%s",
_("sgio is only supported for scsi host device")); _("sgio is only supported for scsi host device"));
goto error; goto error;
@ -10255,6 +10272,22 @@ virDomainHostdevMatchSubsysSCSIHost(virDomainHostdevDefPtr first,
return 0; 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 static int
virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a, virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a,
virDomainHostdevDefPtr b) virDomainHostdevDefPtr b)
@ -10268,7 +10301,11 @@ virDomainHostdevMatchSubsys(virDomainHostdevDefPtr a,
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
return virDomainHostdevMatchSubsysUSB(a, b); return virDomainHostdevMatchSubsysUSB(a, b);
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: 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; return 0;
} }

View File

@ -388,6 +388,15 @@ typedef enum {
VIR_ENUM_DECL(virDomainHostdevSubsysPCIBackend) 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 struct _virDomainHostdevSubsysUSB virDomainHostdevSubsysUSB;
typedef virDomainHostdevSubsysUSB *virDomainHostdevSubsysUSBPtr; typedef virDomainHostdevSubsysUSB *virDomainHostdevSubsysUSBPtr;
struct _virDomainHostdevSubsysUSB { struct _virDomainHostdevSubsysUSB {
@ -416,12 +425,23 @@ struct _virDomainHostdevSubsysSCSIHost {
unsigned unit; 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 struct _virDomainHostdevSubsysSCSI virDomainHostdevSubsysSCSI;
typedef virDomainHostdevSubsysSCSI *virDomainHostdevSubsysSCSIPtr; typedef virDomainHostdevSubsysSCSI *virDomainHostdevSubsysSCSIPtr;
struct _virDomainHostdevSubsysSCSI { struct _virDomainHostdevSubsysSCSI {
int protocol; /* enum virDomainHostdevSCSIProtocolType */
int sgio; /* enum virDomainDeviceSGIO */ int sgio; /* enum virDomainDeviceSGIO */
union { union {
virDomainHostdevSubsysSCSIHost host; virDomainHostdevSubsysSCSIHost host;
virDomainHostdevSubsysSCSIiSCSI iscsi;
} u; } u;
}; };

View File

@ -307,18 +307,31 @@ qemuSetupHostdevCGroup(virDomainObjPtr vm,
break; break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; if (scsisrc->protocol ==
if ((scsi = virSCSIDeviceNew(NULL, VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
scsihostsrc->adapter, scsihostsrc->bus, virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc = &scsisrc->u.iscsi;
scsihostsrc->target, scsihostsrc->unit, /* Follow qemuSetupDiskCgroup() and qemuSetImageCgroupInternal()
dev->readonly, * which does nothing for non local storage
dev->shareable)) == NULL) */
goto cleanup; 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, if (virSCSIDeviceFileIterate(scsi,
qemuSetupHostSCSIDeviceCgroup, qemuSetupHostSCSIDeviceCgroup,
vm) < 0) vm) < 0)
goto cleanup; goto cleanup;
}
break; break;
} }

View File

@ -5124,13 +5124,11 @@ qemuBuildUSBHostdevUSBDevStr(virDomainHostdevDefPtr dev)
return ret; return ret;
} }
char * static char *
qemuBuildSCSIHostdevDrvStr(virConnectPtr conn ATTRIBUTE_UNUSED, qemuBuildSCSIHostHostdevDrvStr(virDomainHostdevDefPtr dev,
virDomainHostdevDefPtr dev, virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED,
virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED, qemuBuildCommandLineCallbacksPtr callbacks)
qemuBuildCommandLineCallbacksPtr callbacks)
{ {
virBuffer buf = VIR_BUFFER_INITIALIZER;
virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
char *sg = NULL; char *sg = NULL;
@ -5140,10 +5138,64 @@ qemuBuildSCSIHostdevDrvStr(virConnectPtr conn ATTRIBUTE_UNUSED,
scsihostsrc->bus, scsihostsrc->bus,
scsihostsrc->target, scsihostsrc->target,
scsihostsrc->unit); scsihostsrc->unit);
if (!sg) return sg;
goto error; }
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", virBufferAsprintf(&buf, ",id=%s-%s",
virDomainDeviceAddressTypeToString(dev->info->type), virDomainDeviceAddressTypeToString(dev->info->type),
dev->info->alias); dev->info->alias);
@ -5162,10 +5214,10 @@ qemuBuildSCSIHostdevDrvStr(virConnectPtr conn ATTRIBUTE_UNUSED,
if (virBufferCheckError(&buf) < 0) if (virBufferCheckError(&buf) < 0)
goto error; goto error;
VIR_FREE(sg); VIR_FREE(source);
return virBufferContentAndReset(&buf); return virBufferContentAndReset(&buf);
error: error:
VIR_FREE(sg); VIR_FREE(source);
virBufferFreeAndReset(&buf); virBufferFreeAndReset(&buf);
return NULL; return NULL;
} }

View File

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

View File

@ -825,6 +825,12 @@ AppArmorSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
return 0; 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) if (profile_loaded(secdef->imagelabel) < 0)
return 0; return 0;

View File

@ -520,6 +520,12 @@ virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
return 0; 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.manager = mgr;
cbdata.secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME); cbdata.secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_DAC_NAME);
@ -648,6 +654,12 @@ virSecurityDACRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
return 0; 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) { switch ((virDomainHostdevSubsysType) dev->source.subsys.type) {
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
virUSBDevicePtr usb; virUSBDevicePtr usb;

View File

@ -1324,6 +1324,12 @@ virSecuritySELinuxSetSecurityHostdevSubsysLabel(virDomainDefPtr def,
virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
int ret = -1; 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) { switch (dev->source.subsys.type) {
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
virUSBDevicePtr usb; virUSBDevicePtr usb;
@ -1511,6 +1517,12 @@ virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(virSecurityManagerPtr mgr,
virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi; virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
int ret = -1; 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) { switch (dev->source.subsys.type) {
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: { case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
virUSBDevicePtr usb; virUSBDevicePtr usb;

View File

@ -920,6 +920,43 @@ virHostdevUpdateActiveUSBDevices(virHostdevManagerPtr mgr,
return ret; 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 int
virHostdevUpdateActiveSCSIDevices(virHostdevManagerPtr mgr, virHostdevUpdateActiveSCSIDevices(virHostdevManagerPtr mgr,
virDomainHostdevDefPtr *hostdevs, virDomainHostdevDefPtr *hostdevs,
@ -930,40 +967,26 @@ virHostdevUpdateActiveSCSIDevices(virHostdevManagerPtr mgr,
virDomainHostdevDefPtr hostdev = NULL; virDomainHostdevDefPtr hostdev = NULL;
size_t i; size_t i;
int ret = -1; int ret = -1;
virSCSIDevicePtr scsi = NULL;
virSCSIDevicePtr tmp = NULL;
if (!nhostdevs) if (!nhostdevs)
return 0; return 0;
virObjectLock(mgr->activeSCSIHostdevs); virObjectLock(mgr->activeSCSIHostdevs);
for (i = 0; i < nhostdevs; i++) { for (i = 0; i < nhostdevs; i++) {
virDomainHostdevSubsysSCSIHostPtr scsihostsrc; virDomainHostdevSubsysSCSIPtr scsisrc;
hostdev = hostdevs[i]; 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 || if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)
continue; continue;
if (!(scsi = virSCSIDeviceNew(NULL, if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
scsihostsrc->adapter, scsihostsrc->bus, continue; /* Not supported for iSCSI */
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 { } else {
if (virSCSIDeviceSetUsedBy(scsi, drv_name, dom_name) < 0 || if (virHostdevUpdateActiveSCSIHostDevices(mgr, hostdev, scsisrc,
virSCSIDeviceListAdd(mgr->activeSCSIHostdevs, scsi) < 0) { drv_name, dom_name) < 0)
virSCSIDeviceFree(scsi);
goto cleanup; goto cleanup;
}
} }
} }
ret = 0; ret = 0;
@ -1193,6 +1216,38 @@ virHostdevPrepareUSBDevices(virHostdevManagerPtr hostdev_mgr,
return ret; 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 int
virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr, virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr,
const char *drv_name, const char *drv_name,
@ -1219,29 +1274,17 @@ virHostdevPrepareSCSIDevices(virHostdevManagerPtr hostdev_mgr,
/* Loop 1: build temporary list */ /* Loop 1: build temporary list */
for (i = 0; i < nhostdevs; i++) { for (i = 0; i < nhostdevs; i++) {
virDomainHostdevDefPtr hostdev = hostdevs[i]; virDomainHostdevDefPtr hostdev = hostdevs[i];
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi;
&hostdev->source.subsys.u.scsi.u.host;
virSCSIDevicePtr scsi;
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)
continue; continue;
if (hostdev->managed) { if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI) {
virReportError(VIR_ERR_XML_ERROR, "%s", continue; /* Not supported for iSCSI */
_("SCSI host device doesn't support managed mode")); } else {
goto cleanup; if (virHostdevPrepareSCSIHostDevices(hostdev, scsisrc, list) < 0)
} 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;
} }
} }
@ -1366,6 +1409,48 @@ virHostdevReAttachUSBDevices(virHostdevManagerPtr hostdev_mgr,
virObjectUnlock(hostdev_mgr->activeUSBHostdevs); 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 void
virHostdevReAttachSCSIDevices(virHostdevManagerPtr hostdev_mgr, virHostdevReAttachSCSIDevices(virHostdevManagerPtr hostdev_mgr,
const char *drv_name, const char *drv_name,
@ -1381,44 +1466,17 @@ virHostdevReAttachSCSIDevices(virHostdevManagerPtr hostdev_mgr,
virObjectLock(hostdev_mgr->activeSCSIHostdevs); virObjectLock(hostdev_mgr->activeSCSIHostdevs);
for (i = 0; i < nhostdevs; i++) { for (i = 0; i < nhostdevs; i++) {
virDomainHostdevDefPtr hostdev = hostdevs[i]; virDomainHostdevDefPtr hostdev = hostdevs[i];
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = virDomainHostdevSubsysSCSIPtr scsisrc = &hostdev->source.subsys.u.scsi;
&hostdev->source.subsys.u.scsi.u.host;
virSCSIDevicePtr scsi;
virSCSIDevicePtr tmp;
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI) hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI)
continue; continue;
if (!(scsi = virSCSIDeviceNew(NULL, if (scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
scsihostsrc->adapter, scsihostsrc->bus, continue; /* Not supported for iSCSI */
scsihostsrc->target, scsihostsrc->unit, else
hostdev->readonly, hostdev->shareable))) { virHostdevReAttachSCSIHostDevices(hostdev_mgr, hostdev, scsisrc,
VIR_WARN("Unable to reattach SCSI device %s:%d:%d:%d on domain %s", drv_name, dom_name);
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);
} }
virObjectUnlock(hostdev_mgr->activeSCSIHostdevs); virObjectUnlock(hostdev_mgr->activeSCSIHostdevs);
} }