[libvirt] [PATCHv3] avoid false creation discard pool definition
by Wen Ruo Lv
False pool creation will clear previous definition.
This patch roll back to previous definition after pool-creat fails
ref:
http://www.redhat.com/archives/libvir-list/2011-November/msg01152.html
http://www.redhat.com/archives/libvir-list/2011-November/msg01152.html
Signed-off-by: Wen Ruo Lv <lvroyce(a)linux.vnet.ibm.com>
---
src/conf/storage_conf.c | 30 +++++++++++++++++++++++++-----
src/conf/storage_conf.h | 4 ++--
src/libvirt_private.syms | 1 +
src/storage/storage_driver.c | 36 ++++++++++++++++++++++++------------
src/test/test_driver.c | 18 +++++++++---------
5 files changed, 61 insertions(+), 28 deletions(-)
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index dadc115..bf82eb6 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -1385,17 +1385,20 @@ virStorageVolDefFindByName(virStoragePoolObjPtr pool,
virStoragePoolObjPtr
virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
- virStoragePoolDefPtr def) {
+ virStoragePoolDefPtr *pdef) {
virStoragePoolObjPtr pool;
+ virStoragePoolDefPtr lastDef;
+ virStoragePoolDefPtr def = *pdef;
if ((pool = virStoragePoolObjFindByName(pools, def->name))) {
if (!virStoragePoolObjIsActive(pool)) {
- virStoragePoolDefFree(pool->def);
+ lastDef = pool->def;
pool->def = def;
} else {
- virStoragePoolDefFree(pool->newDef);
+ lastDef = pool->newDef;
pool->newDef = def;
}
+ *pdef = lastDef;
return pool;
}
@@ -1421,11 +1424,26 @@ virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
virReportOOMError();
return NULL;
}
+ *pdef = NULL;
pools->objs[pools->count++] = pool;
return pool;
}
+void virStoragePoolObjDefRollBack(virStoragePoolObjPtr pool, virStoragePoolDefPtr *lastDef)
+{
+ virStoragePoolDefPtr tmpDef;
+
+ if (pool->active) {
+ tmpDef = pool->newDef;
+ pool->newDef = *lastDef;
+ }
+ else {
+ tmpDef = pool->def;
+ pool->def = *lastDef;
+ }
+ *lastDef = tmpDef;
+}
static virStoragePoolObjPtr
virStoragePoolObjLoad(virStoragePoolObjListPtr pools,
const char *file,
@@ -1446,7 +1464,7 @@ virStoragePoolObjLoad(virStoragePoolObjListPtr pools,
return NULL;
}
- if (!(pool = virStoragePoolObjAssignDef(pools, def))) {
+ if (!(pool = virStoragePoolObjAssignDef(pools, &def))) {
virStoragePoolDefFree(def);
return NULL;
}
@@ -1455,6 +1473,7 @@ virStoragePoolObjLoad(virStoragePoolObjListPtr pools,
pool->configFile = strdup(path);
if (pool->configFile == NULL) {
virReportOOMError();
+ virStoragePoolObjDefRollBack(pool, &def);
virStoragePoolDefFree(def);
return NULL;
}
@@ -1462,13 +1481,14 @@ virStoragePoolObjLoad(virStoragePoolObjListPtr pools,
pool->autostartLink = strdup(autostartLink);
if (pool->autostartLink == NULL) {
virReportOOMError();
+ virStoragePoolObjDefRollBack(pool, &def);
virStoragePoolDefFree(def);
return NULL;
}
pool->autostart = virFileLinkPointsTo(pool->autostartLink,
pool->configFile);
-
+ virStoragePoolDefFree(def);
return pool;
}
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 19bbd2c..dc9dc05 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -364,8 +364,8 @@ char *virStorageVolDefFormat(virStoragePoolDefPtr pool,
virStorageVolDefPtr def);
virStoragePoolObjPtr virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
- virStoragePoolDefPtr def);
-
+ virStoragePoolDefPtr *def);
+void virStoragePoolObjDefRollBack(virStoragePoolObjPtr pool,virStoragePoolDefPtr *lastDef);
int virStoragePoolObjSaveDef(virStorageDriverStatePtr driver,
virStoragePoolObjPtr pool,
virStoragePoolDefPtr def);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0b21cdc..391998c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -975,6 +975,7 @@ virStoragePoolLoadAllConfigs;
virStoragePoolObjAssignDef;
virStoragePoolObjClearVols;
virStoragePoolObjDeleteDef;
+virStoragePoolObjDefRollBack;
virStoragePoolObjFindByName;
virStoragePoolObjFindByUUID;
virStoragePoolObjIsDuplicate;
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index 8c2d6e1..4ea22d5 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -526,6 +526,7 @@ storagePoolCreate(virConnectPtr conn,
virStoragePoolObjPtr pool = NULL;
virStoragePoolPtr ret = NULL;
virStorageBackendPtr backend;
+ int dupPool;
virCheckFlags(0, NULL);
@@ -533,7 +534,7 @@ storagePoolCreate(virConnectPtr conn,
if (!(def = virStoragePoolDefParseString(xml)))
goto cleanup;
- if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0)
+ if ((dupPool = virStoragePoolObjIsDuplicate(&driver->pools, def, 1)) < 0)
goto cleanup;
if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
@@ -542,22 +543,29 @@ storagePoolCreate(virConnectPtr conn,
if ((backend = virStorageBackendForType(def->type)) == NULL)
goto cleanup;
- if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
+ if (!(pool = virStoragePoolObjAssignDef(&driver->pools, &def)))
goto cleanup;
- def = NULL;
if (backend->startPool &&
backend->startPool(conn, pool) < 0) {
- virStoragePoolObjRemove(&driver->pools, pool);
- pool = NULL;
+ if (dupPool)
+ virStoragePoolObjDefRollBack(pool, &def);
+ else {
+ virStoragePoolObjRemove(&driver->pools, pool);
+ pool = NULL;
+ }
goto cleanup;
}
if (backend->refreshPool(conn, pool) < 0) {
if (backend->stopPool)
backend->stopPool(conn, pool);
- virStoragePoolObjRemove(&driver->pools, pool);
- pool = NULL;
+ if (dupPool)
+ virStoragePoolObjDefRollBack(pool, &def);
+ else {
+ virStoragePoolObjRemove(&driver->pools, pool);
+ pool = NULL;
+ }
goto cleanup;
}
VIR_INFO("Creating storage pool '%s'", pool->def->name);
@@ -582,6 +590,7 @@ storagePoolDefine(virConnectPtr conn,
virStoragePoolDefPtr def;
virStoragePoolObjPtr pool = NULL;
virStoragePoolPtr ret = NULL;
+ int dupPool;
virCheckFlags(0, NULL);
@@ -589,7 +598,7 @@ storagePoolDefine(virConnectPtr conn,
if (!(def = virStoragePoolDefParseString(xml)))
goto cleanup;
- if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0)
+ if ((dupPool = virStoragePoolObjIsDuplicate(&driver->pools, def, 0)) < 0)
goto cleanup;
if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
@@ -598,15 +607,18 @@ storagePoolDefine(virConnectPtr conn,
if (virStorageBackendForType(def->type) == NULL)
goto cleanup;
- if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
+ if (!(pool = virStoragePoolObjAssignDef(&driver->pools, &def)))
goto cleanup;
if (virStoragePoolObjSaveDef(driver, pool, def) < 0) {
- virStoragePoolObjRemove(&driver->pools, pool);
- def = NULL;
+ if (dupPool)
+ virStoragePoolObjDefRollBack(pool, &def);
+ else {
+ virStoragePoolObjRemove(&driver->pools, pool);
+ pool = NULL;
+ }
goto cleanup;
}
- def = NULL;
VIR_INFO("Defining storage pool '%s'", pool->def->name);
ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
diff --git a/src/test/test_driver.c b/src/test/test_driver.c
index ce94a17..65dd606 100644
--- a/src/test/test_driver.c
+++ b/src/test/test_driver.c
@@ -594,10 +594,8 @@ static int testOpenDefault(virConnectPtr conn) {
goto error;
if (!(poolobj = virStoragePoolObjAssignDef(&privconn->pools,
- pooldef))) {
- virStoragePoolDefFree(pooldef);
+ &pooldef)))
goto error;
- }
if (testStoragePoolObjSetDefaults(poolobj) == -1) {
virStoragePoolObjUnlock(poolobj);
@@ -614,13 +612,14 @@ static int testOpenDefault(virConnectPtr conn) {
virNodeDeviceDefFree(nodedef);
goto error;
}
+ virStoragePoolDefFree(pooldef);
virNodeDeviceObjUnlock(nodeobj);
testDriverUnlock(privconn);
return VIR_DRV_OPEN_SUCCESS;
-
error:
+ virStoragePoolDefFree(pooldef);
virDomainObjListDeinit(&privconn->domains);
virNetworkObjListFree(&privconn->networks);
virInterfaceObjListFree(&privconn->ifaces);
@@ -1016,12 +1015,13 @@ static int testOpenFromFile(virConnectPtr conn,
}
if (!(pool = virStoragePoolObjAssignDef(&privconn->pools,
- def))) {
+ &def))) {
virStoragePoolDefFree(def);
goto error;
}
if (testStoragePoolObjSetDefaults(pool) == -1) {
+ virStoragePoolDefFree(def);
virStoragePoolObjUnlock(pool);
goto error;
}
@@ -1029,10 +1029,12 @@ static int testOpenFromFile(virConnectPtr conn,
/* Find storage volumes */
if (testOpenVolumesForPool(xml, ctxt, file, pool, i+1) < 0) {
+ virStoragePoolDefFree(def);
virStoragePoolObjUnlock(pool);
goto error;
}
+ virStoragePoolDefFree(def);
virStoragePoolObjUnlock(pool);
}
VIR_FREE(pools);
@@ -4123,9 +4125,8 @@ testStoragePoolCreate(virConnectPtr conn,
goto cleanup;
}
- if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
+ if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, &def)))
goto cleanup;
- def = NULL;
if (testStoragePoolObjSetDefaults(pool) == -1) {
virStoragePoolObjRemove(&privconn->pools, pool);
@@ -4164,9 +4165,8 @@ testStoragePoolDefine(virConnectPtr conn,
def->allocation = defaultPoolAlloc;
def->available = defaultPoolCap - defaultPoolAlloc;
- if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, def)))
+ if (!(pool = virStoragePoolObjAssignDef(&privconn->pools, &def)))
goto cleanup;
- def = NULL;
if (testStoragePoolObjSetDefaults(pool) == -1) {
virStoragePoolObjRemove(&privconn->pools, pool);
--
1.7.4.1
12 years, 12 months
[libvirt] [PATCH v2] avoid false pool creation discard pool definition
by Wen Ruo Lv
False pool creation will clear previous definition.
This patch roll back to previous definition after pool-creat fails
ref:
http://www.redhat.com/archives/libvir-list/2011-November/msg01152.html
http://www.redhat.com/archives/libvir-list/2011-November/msg01152.html
Signed-off-by: Wen Ruo Lv <lvroyce(a)linux.vnet.ibm.com>
---
src/conf/storage_conf.c | 15 +++++++++++++--
src/conf/storage_conf.h | 2 +-
src/libvirt_private.syms | 1 +
src/storage/storage_driver.c | 32 ++++++++++++++++++++++----------
4 files changed, 37 insertions(+), 13 deletions(-)
diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c
index dadc115..4186036 100644
--- a/src/conf/storage_conf.c
+++ b/src/conf/storage_conf.c
@@ -1387,15 +1387,17 @@ virStoragePoolObjPtr
virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
virStoragePoolDefPtr def) {
virStoragePoolObjPtr pool;
+ virStoragePoolDefPtr lastDef;
if ((pool = virStoragePoolObjFindByName(pools, def->name))) {
if (!virStoragePoolObjIsActive(pool)) {
- virStoragePoolDefFree(pool->def);
+ lastDef = pool->def;
pool->def = def;
} else {
- virStoragePoolDefFree(pool->newDef);
+ lastDef = pool->newDef;
pool->newDef = def;
}
+ def = lastDef;
return pool;
}
@@ -1413,6 +1415,7 @@ virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
virStoragePoolObjLock(pool);
pool->active = 0;
pool->def = def;
+ def = NULL;
if (VIR_REALLOC_N(pools->objs, pools->count+1) < 0) {
pool->def = NULL;
@@ -1426,6 +1429,14 @@ virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
return pool;
}
+void virStoragePoolObjDefRollBack(virStoragePoolDefPtr def,virStoragePoolDefPtr lastDef)
+{
+ virStoragePoolDefPtr tmpDef;
+
+ tmpDef = def;
+ def = lastDef;
+ lastDef = tmpDef;
+}
static virStoragePoolObjPtr
virStoragePoolObjLoad(virStoragePoolObjListPtr pools,
const char *file,
diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h
index 19bbd2c..bfd8904 100644
--- a/src/conf/storage_conf.h
+++ b/src/conf/storage_conf.h
@@ -365,7 +365,7 @@ char *virStorageVolDefFormat(virStoragePoolDefPtr pool,
virStoragePoolObjPtr virStoragePoolObjAssignDef(virStoragePoolObjListPtr pools,
virStoragePoolDefPtr def);
-
+void virStoragePoolObjDefRollBack(virStoragePoolDefPtr def,virStoragePoolDefPtr lastDef);
int virStoragePoolObjSaveDef(virStorageDriverStatePtr driver,
virStoragePoolObjPtr pool,
virStoragePoolDefPtr def);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0b21cdc..391998c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -975,6 +975,7 @@ virStoragePoolLoadAllConfigs;
virStoragePoolObjAssignDef;
virStoragePoolObjClearVols;
virStoragePoolObjDeleteDef;
+virStoragePoolObjDefRollBack;
virStoragePoolObjFindByName;
virStoragePoolObjFindByUUID;
virStoragePoolObjIsDuplicate;
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index 8c2d6e1..2e6ae05 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -526,6 +526,7 @@ storagePoolCreate(virConnectPtr conn,
virStoragePoolObjPtr pool = NULL;
virStoragePoolPtr ret = NULL;
virStorageBackendPtr backend;
+ int dupPool;
virCheckFlags(0, NULL);
@@ -533,7 +534,7 @@ storagePoolCreate(virConnectPtr conn,
if (!(def = virStoragePoolDefParseString(xml)))
goto cleanup;
- if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0)
+ if ((dupPool = virStoragePoolObjIsDuplicate(&driver->pools, def, 1)) < 0)
goto cleanup;
if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
@@ -544,20 +545,27 @@ storagePoolCreate(virConnectPtr conn,
if (!(pool = virStoragePoolObjAssignDef(&driver->pools, def)))
goto cleanup;
- def = NULL;
if (backend->startPool &&
backend->startPool(conn, pool) < 0) {
- virStoragePoolObjRemove(&driver->pools, pool);
- pool = NULL;
+ if (dupPool)
+ virStoragePoolObjDefRollBack(pool->def, def);
+ else {
+ virStoragePoolObjRemove(&driver->pools, pool);
+ pool = NULL;
+ }
goto cleanup;
}
if (backend->refreshPool(conn, pool) < 0) {
if (backend->stopPool)
backend->stopPool(conn, pool);
- virStoragePoolObjRemove(&driver->pools, pool);
- pool = NULL;
+ if (dupPool)
+ virStoragePoolObjDefRollBack(pool->def, def);
+ else {
+ virStoragePoolObjRemove(&driver->pools, pool);
+ pool = NULL;
+ }
goto cleanup;
}
VIR_INFO("Creating storage pool '%s'", pool->def->name);
@@ -582,6 +590,7 @@ storagePoolDefine(virConnectPtr conn,
virStoragePoolDefPtr def;
virStoragePoolObjPtr pool = NULL;
virStoragePoolPtr ret = NULL;
+ int dupPool;
virCheckFlags(0, NULL);
@@ -589,7 +598,7 @@ storagePoolDefine(virConnectPtr conn,
if (!(def = virStoragePoolDefParseString(xml)))
goto cleanup;
- if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0)
+ if ((dupPool = virStoragePoolObjIsDuplicate(&driver->pools, def, 0)) < 0)
goto cleanup;
if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0)
@@ -602,11 +611,14 @@ storagePoolDefine(virConnectPtr conn,
goto cleanup;
if (virStoragePoolObjSaveDef(driver, pool, def) < 0) {
- virStoragePoolObjRemove(&driver->pools, pool);
- def = NULL;
+ if (dupPool)
+ virStoragePoolObjDefRollBack(pool->def, def);
+ else {
+ virStoragePoolObjRemove(&driver->pools, pool);
+ pool = NULL;
+ }
goto cleanup;
}
- def = NULL;
VIR_INFO("Defining storage pool '%s'", pool->def->name);
ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid);
--
1.7.4.1
13 years
[libvirt] [PATCH 5/5] If a system has 64 or more VF's, it is quite tedious to mention each VF in the interface pool. The following modification find a Free VF given a Physical Function when mode=passthrough. We also save the state of each VF. Hence modifications to networkAllocateActualDevice, networkNotifyActualDevice and networkReleaseActualDevice were required. The following patch does just that.
by Shradha Shah
---
src/network/bridge_driver.c | 208 +++++++++++++++++++++++++++++++++++++------
1 files changed, 179 insertions(+), 29 deletions(-)
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index c49c25b..a2e3119 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -55,6 +55,7 @@
#include "memory.h"
#include "uuid.h"
#include "iptables.h"
+#include "pci.h"
#include "logging.h"
#include "dnsmasq.h"
#include "configmake.h"
@@ -2823,8 +2824,11 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
goto cleanup;
} else {
int ii;
- virNetworkForwardIfDefPtr dev = NULL;
-
+ virNetworkForwardVfDefPtr dev = NULL;
+ unsigned int vf_found = 0;
+ unsigned int num_virt_fns = 0;
+ struct pci_config_address **virt_fns = NULL;
+
/* pick an interface from the pool */
/* PASSTHROUGH mode, and PRIVATE Mode + 802.1Qbh both require
@@ -2832,32 +2836,105 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
* 0. Other modes can share, so just search for the one with
* the lowest usageCount.
*/
- if ((netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH) ||
- ((netdef->forwardType == VIR_NETWORK_FORWARD_PRIVATE) &&
- iface->data.network.actual->data.direct.virtPortProfile &&
- (iface->data.network.actual->data.direct.virtPortProfile->virtPortType
- == VIR_NETDEV_VPORT_PROFILE_8021QBH))) {
- /* pick first dev with 0 usageCount */
+ if (netdef->forwardType == VIR_NETWORK_FORWARD_PASSTHROUGH) {
+ if (netdef->nForwardIfs == 1) {
+ if (netdef->forwardIfs[0].vfs_in_use_count == 0) {
+ if ((virNetDevGetVirtualFunctions(netdef->forwardIfs[0].dev,
+ &virt_fns, &num_virt_fns)) < 0){
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get Virtual functions on %s"),
+ netdef->forwardIfs[0].dev);
+ goto out;
+ }
+
+ netdef->forwardIfs[0].nForwardVfs = num_virt_fns;
+
+ if ((VIR_ALLOC_N(netdef->forwardIfs[0].forwardVfs,
+ netdef->forwardIfs[0].nForwardVfs)) < 0) {
+ virReportOOMError();
+ goto out;
+ }
+
+ for (ii = 0; ii < netdef->forwardIfs[0].nForwardVfs; ii++) {
+ if ((virNetDevGetNetName(virt_fns[ii],
+ &netdef->forwardIfs[0].forwardVfs[ii].dev)) < 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get Interface name"));
+ goto out;
+ }
+ netdef->forwardIfs[0].forwardVfs[ii].usageCount = 0;
+ }
+ }
+
+ for (ii = 0; ii < netdef->forwardIfs[0].nForwardVfs; ii++) {
+ if (netdef->forwardIfs[0].forwardVfs[ii].usageCount == 0) {
+ netdef->forwardIfs[0].vfs_in_use_count++;
+ dev = &netdef->forwardIfs[0].forwardVfs[ii];
+ vf_found = 1;
+ break;
+ }
+ }
+ /* If No Vf's are present or if Vf's are in use
+ * check whether the PF is free and assign PF
+ * to dev
+ */
+ if(vf_found == 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("No Free Vf's on %s, checking if PF is free"),
+ netdef->forwardIfs[0].dev);
+ if (netdef->forwardIfs[0].usageCount == 0) {
+ dev = (virNetworkForwardVfDef *)&netdef->forwardIfs[0];
+ }
+ }
+ vf_found = 0;
+ }
+ /* If more than 1 ForwardIfs are present check usagecount of each
+ * find the one that is free
+ */
+ else {
+ for (ii = 0; ii < netdef->nForwardIfs; ii++) {
+ if (netdef->forwardIfs[ii].usageCount == 0) {
+ dev = (virNetworkForwardVfDef *)&netdef->forwardIfs[ii];
+ break;
+ }
+ }
+ }
+ }
+ else if ((netdef->forwardType == VIR_NETWORK_FORWARD_PRIVATE) &&
+ iface->data.network.actual->data.direct.virtPortProfile &&
+ (iface->data.network.actual->data.direct.virtPortProfile->virtPortType
+ == VIR_NETDEV_VPORT_PROFILE_8021QBH)) {
+
+
+ /* pick first dev with 0 usageCount */
+
for (ii = 0; ii < netdef->nForwardIfs; ii++) {
if (netdef->forwardIfs[ii].usageCount == 0) {
- dev = &netdef->forwardIfs[ii];
+ dev = (virNetworkForwardVfDef *)&netdef->forwardIfs[ii];
break;
}
}
- } else {
+ }
+ else {
/* pick least used dev */
- dev = &netdef->forwardIfs[0];
+ dev = (virNetworkForwardVfDef *)&netdef->forwardIfs[0];
for (ii = 1; ii < netdef->nForwardIfs; ii++) {
if (netdef->forwardIfs[ii].usageCount < dev->usageCount)
- dev = &netdef->forwardIfs[ii];
+ dev = (virNetworkForwardVfDef *)&netdef->forwardIfs[ii];
}
}
+
+ out:
+ for (ii = 0; ii < num_virt_fns; ii++)
+ VIR_FREE(virt_fns[ii]);
+ VIR_FREE(virt_fns);
+
/* dev points at the physical device we want to use */
if (!dev) {
networkReportError(VIR_ERR_INTERNAL_ERROR,
_("network '%s' requires exclusive access to interfaces, but none are available"),
- netdef->name);
+ netdef->name);
goto cleanup;
}
iface->data.network.actual->data.direct.linkdev = strdup(dev->dev);
@@ -2871,7 +2948,7 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
dev->dev, dev->usageCount);
}
}
-
+
ret = 0;
cleanup:
if (network)
@@ -2935,17 +3012,55 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
netdef->name);
goto cleanup;
} else {
- int ii;
- virNetworkForwardIfDefPtr dev = NULL;
-
+ int ii, jj, isVf;
+ virNetworkForwardVfDefPtr dev = NULL;
+ char *pfDeviceName;
+
/* find the matching interface in the pool and increment its usageCount */
+
+ isVf = virNetDevIsVirtualFunction(actualDev);
- for (ii = 0; ii < netdef->nForwardIfs; ii++) {
- if (STREQ(actualDev, netdef->forwardIfs[ii].dev)) {
- dev = &netdef->forwardIfs[ii];
- break;
+ if (isVf == 1) {
+ /*If Vf get PF : pciGetPhysicalFunction */
+ if ((virNetDevGetPhysicalFunction(actualDev, &pfDeviceName)) < 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get Physical functions for %s"),
+ actualDev);
+ goto out;
+ }
+
+ /* Find the matching PF from the list of netdef->forwardIfs
+ * Search through the ForwardVfs list of the PF to find the VF
+ */
+ for (ii = 0; ii < netdef->nForwardIfs; ii++) {
+ if (STREQ(pfDeviceName, netdef->forwardIfs[ii].dev)) {
+ for (jj = 0; jj < netdef->forwardIfs[ii].nForwardVfs; jj++) {
+ if (STREQ(actualDev, netdef->forwardIfs[ii].forwardVfs[jj].dev)) {
+ dev = &netdef->forwardIfs[ii].forwardVfs[jj];
+ break;
+ }
+ }
+ }
}
}
+ else if (isVf == 0) {
+ /*If the actual dev is a PF do the following code*/
+ for (ii = 0; ii < netdef->nForwardIfs; ii++) {
+ if (STREQ(actualDev, netdef->forwardIfs[ii].dev)) {
+ dev = (virNetworkForwardVfDef *)&netdef->forwardIfs[ii];
+ break;
+ }
+ }
+ }
+ else {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find whether %s is PF or VF"),
+ actualDev);
+ goto out;
+ }
+
+ out:
+
/* dev points at the physical device we want to use */
if (!dev) {
networkReportError(VIR_ERR_INTERNAL_ERROR,
@@ -2953,7 +3068,7 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
netdef->name, actualDev);
goto cleanup;
}
-
+
/* PASSTHROUGH mode, and PRIVATE Mode + 802.1Qbh both require
* exclusive access to a device, so current usageCount must be
* 0 in those cases.
@@ -3036,15 +3151,50 @@ networkReleaseActualDevice(virDomainNetDefPtr iface)
netdef->name);
goto cleanup;
} else {
- int ii;
- virNetworkForwardIfDefPtr dev = NULL;
-
- for (ii = 0; ii < netdef->nForwardIfs; ii++) {
- if (STREQ(actualDev, netdef->forwardIfs[ii].dev)) {
- dev = &netdef->forwardIfs[ii];
- break;
+ int ii, jj, isVf;
+ virNetworkForwardVfDefPtr dev = NULL;
+ char *pfDeviceName;
+
+ isVf = virNetDevIsVirtualFunction(actualDev);
+
+ if (isVf == 1) {
+ /*If Vf get PF */
+ if ((virNetDevGetPhysicalFunction(actualDev, &pfDeviceName)) < 0) {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not get Physical functions for %s"),
+ actualDev);
+ goto out;
}
+
+ /* Find the matching PF from the list of netdef->forwardIfs
+ * search through the ForwardVfs list of the PF to find the VF
+ */
+ for (ii = 0; ii < netdef->nForwardIfs; ii++) {
+ if (STREQ(pfDeviceName, netdef->forwardIfs[ii].dev)) {
+ for (jj = 0; jj < netdef->forwardIfs[ii].nForwardVfs; jj++) {
+ if (STREQ(actualDev, netdef->forwardIfs[ii].forwardVfs[jj].dev)) {
+ dev = &netdef->forwardIfs[ii].forwardVfs[jj];
+ break;
+ }
+ }
+ }
+ }
+ }
+ else if (isVf == 0) {
+ for (ii = 0; ii < netdef->nForwardIfs; ii++) {
+ if (STREQ(actualDev, netdef->forwardIfs[ii].dev)) {
+ dev = (virNetworkForwardVfDef *)&netdef->forwardIfs[ii];
+ break;
+ }
+ }
+ }
+ else {
+ networkReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not find whether %s is PF or VF"),
+ actualDev);
+ goto out;
}
+ out:
/* dev points at the physical device we've been using */
if (!dev) {
networkReportError(VIR_ERR_INTERNAL_ERROR,
--
1.7.4.4
13 years
[libvirt] [PATCH 4/5] Addition of a new device structure to store the state of a Virtual Function Modifications to the Physical Device Structure to store state of its Virtual Functions
by Shradha Shah
---
src/conf/network_conf.c | 19 ++++++++++++++++++-
src/conf/network_conf.h | 10 ++++++++++
2 files changed, 28 insertions(+), 1 deletions(-)
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index 10afcde..d30d757 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -43,6 +43,7 @@
#include "buf.h"
#include "c-ctype.h"
#include "virfile.h"
+#include "logging.h"
#define MAX_BRIDGE_ID 256
#define VIR_FROM_THIS VIR_FROM_NETWORK
@@ -103,6 +104,12 @@ virNetworkForwardIfDefClear(virNetworkForwardIfDefPtr def)
VIR_FREE(def->dev);
}
+static void
+virNetworkForwardVfDefClear(virNetworkForwardVfDefPtr def)
+{
+ VIR_FREE(def->dev);
+}
+
static void virNetworkIpDefClear(virNetworkIpDefPtr def)
{
int ii;
@@ -144,7 +151,7 @@ static void virNetworkDNSDefFree(virNetworkDNSDefPtr def)
void virNetworkDefFree(virNetworkDefPtr def)
{
- int ii;
+ int ii, jj;
if (!def)
return;
@@ -154,6 +161,10 @@ void virNetworkDefFree(virNetworkDefPtr def)
VIR_FREE(def->domain);
for (ii = 0 ; ii < def->nForwardIfs && def->forwardIfs ; ii++) {
+ for (jj = 0 ; jj < (def->forwardIfs[ii]).nForwardVfs ; jj++) {
+ virNetworkForwardVfDefClear(&(def->forwardIfs[ii].forwardVfs[jj]));
+ }
+ VIR_FREE(def->forwardIfs[ii].forwardVfs);
virNetworkForwardIfDefClear(&def->forwardIfs[ii]);
}
VIR_FREE(def->forwardIfs);
@@ -979,6 +990,9 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
if (forwardDev) {
def->forwardIfs[0].usageCount = 0;
+ def->forwardIfs[0].vfs_in_use_count = 0;
+ def->forwardIfs[0].nForwardVfs = 0;
+ def->forwardIfs[0].forwardVfs = NULL;
def->forwardIfs[0].dev = forwardDev;
forwardDev = NULL;
def->nForwardIfs++;
@@ -1011,6 +1025,9 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
def->forwardIfs[ii].dev = forwardDev;
forwardDev = NULL;
def->forwardIfs[ii].usageCount = 0;
+ def->forwardIfs[ii].vfs_in_use_count = 0;
+ def->forwardIfs[ii].nForwardVfs = 0;
+ def->forwardIfs[ii].forwardVfs = NULL;
def->nForwardIfs++;
}
}
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index 1be20f8..d1dba94 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -112,11 +112,21 @@ struct _virNetworkIpDef {
virSocketAddr bootserver;
};
+typedef struct _virNetworkForwardVfDef virNetworkForwardVfDef;
+typedef virNetworkForwardVfDef *virNetworkForwardVfDefPtr;
+struct _virNetworkForwardVfDef {
+ char *dev;
+ int usageCount;
+};
+
typedef struct _virNetworkForwardIfDef virNetworkForwardIfDef;
typedef virNetworkForwardIfDef *virNetworkForwardIfDefPtr;
struct _virNetworkForwardIfDef {
char *dev; /* name of device */
int usageCount; /* how many guest interfaces are bound to this device? */
+ int vfs_in_use_count; /*if SRIOV, Are any of the Vf's on the dev in use? */
+ size_t nForwardVfs;
+ virNetworkForwardVfDefPtr forwardVfs;
};
typedef struct _virPortGroupDef virPortGroupDef;
--
1.7.4.4
13 years
[libvirt] [PATCH 3/5] Adding functions virNetDevGetVirtualFunctions and virNetDevGetNetName virNetDevGetVirtualFunctions: Gets the BDF of all the Virtual Functions given a physical function virNetDevGetNetName: Gets the interface name of the PCI Device.
by Shradha Shah
---
src/util/virnetdev.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++
src/util/virnetdev.h | 10 ++++++
2 files changed, 99 insertions(+), 0 deletions(-)
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index 86196a1..d07d8fa 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -968,6 +968,76 @@ virNetDevSysfsDeviceFile(char **pf_sysfs_device_link, const char *ifname,
}
/**
+ * virNetDevGetVirtualFunctions:
+ *
+ * @pfname : name of the physical function interface name
+ * @virt_fns: array that will hold the pointers to the virtual_functions
+ * @num_virt_fns: number of virtual functions
+ *
+ * Returns 0 on success and -1 on failure
+ */
+
+int
+virNetDevGetVirtualFunctions(const char *pfname,
+ struct pci_config_address ***virt_fns,
+ unsigned int *num_virt_fns)
+{
+ int ret = -1;
+ char *pf_sysfs_device_link = NULL;
+
+
+ if (virNetDevSysfsFile(&pf_sysfs_device_link, pfname, "device") < 0)
+ return ret;
+
+ if (pciGetVirtualFunctions(pf_sysfs_device_link, virt_fns,
+ num_virt_fns) < 0)
+ goto out;
+ ret = 0;
+
+out:
+ VIR_FREE(pf_sysfs_device_link);
+ return ret;
+}
+
+/**
+ * virNetDevGetNetName:
+ *
+ * @vf : pci address (BDF) of the Virtual Function
+ * @vfname: interface name of the virtual function returned by this function
+ *
+ * Returns 0 on success and -1 on failure
+ */
+
+int
+virNetDevGetNetName(struct pci_config_address *vf, char **vfname)
+{
+ int ret = -1;
+ pciDevice *dev = NULL;
+ char *pci_sysfs_device_link = NULL;
+
+ dev = pciGetDevice(vf->domain, vf->bus, vf->slot, vf->function);
+ if (dev != NULL) {
+ if (pciSysfsFile(&pci_sysfs_device_link, dev->name) < 0) {
+ virReportSystemError(ENOSYS, "%s",
+ _("Failed to get PCI SYSFS file"));
+ goto out;
+ }
+
+ if (pciDeviceNetName(pci_sysfs_device_link, vfname) < 0) {
+ virReportSystemError(ENOSYS, "%s",
+ _("Failed to get interface name of the VF"));
+ goto out;
+ }
+ }
+ ret = 0;
+
+out:
+ VIR_FREE(pci_sysfs_device_link);
+ pciFreeDevice(dev);
+ return ret;
+}
+
+/**
* virNetDevIsVirtualFunction:
* @ifname : name of the interface
*
@@ -1055,6 +1125,25 @@ virNetDevGetPhysicalFunction(const char *ifname, char **pfname)
}
#else /* !__linux__ */
int
+virNetDevGetVirtualFunctions(const char *pfname ATTRIBUTE_UNUSED,
+ struct pci_config_address ***virt_fns ATTRIBUTE_UNUSED,
+ unsigned int *num_virt_fns ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS, "%s",
+ _("Unable to get virtual functions on this platfornm"));
+ return -1;
+}
+
+int
+virNetDevGetNetName(struct pci_config_address *vf ATTRIBUTE_UNUSED,
+ char **vfname ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS, "%s",
+ _("Unable to get Device name on this platfornm"));
+ return -1;
+}
+
+int
virNetDevIsVirtualFunction(const char *ifname ATTRIBUTE_UNUSED)
{
virReportSystemError(ENOSYS, "%s",
diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
index 13ba1da..4d1573a 100644
--- a/src/util/virnetdev.h
+++ b/src/util/virnetdev.h
@@ -24,6 +24,7 @@
# define __VIR_NETDEV_H__
# include "virsocketaddr.h"
+# include "pci.h"
int virNetDevExists(const char *brname)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
@@ -99,4 +100,13 @@ int virNetDevGetVirtualFunctionIndex(const char *pfname, const char *vfname,
int virNetDevGetPhysicalFunction(const char *ifname, char **pfname)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+int virNetDevGetVirtualFunctions(const char *pfname,
+ struct pci_config_address ***virt_fns,
+ unsigned int *num_virt_fns)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+ ATTRIBUTE_RETURN_CHECK;
+
+int virNetDevGetNetName(struct pci_config_address *vf, char **vfname)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+
#endif /* __VIR_NETDEV_H__ */
--
1.7.4.4
13 years
[libvirt] [PATCH 2/5] Added function pciSysfsFile to enable access to the PCI SYSFS files.
by Shradha Shah
---
src/util/pci.c | 17 +++++++++++++++++
src/util/pci.h | 2 ++
2 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/src/util/pci.c b/src/util/pci.c
index 857078d..89a9d12 100644
--- a/src/util/pci.c
+++ b/src/util/pci.c
@@ -39,6 +39,7 @@
#include "command.h"
#include "virterror_internal.h"
#include "virfile.h"
+#include "virnetdev.h"
/* avoid compilation breakage on some systems */
#ifndef MODPROBE
@@ -1991,6 +1992,22 @@ out:
return ret;
}
+ /*
+ * Returns a path to the PCI sysfs file given the BDF of the PCI function
+ */
+
+int
+pciSysfsFile(char **pci_sysfs_device_link, char *pciDeviceName)
+{
+ if (virAsprintf(pci_sysfs_device_link, PCI_SYSFS "devices/%s",
+ pciDeviceName) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ return 0;
+}
+
/*
* Returns the network device name of a pci device
*/
diff --git a/src/util/pci.h b/src/util/pci.h
index 8e47fc2..3800d98 100644
--- a/src/util/pci.h
+++ b/src/util/pci.h
@@ -143,4 +143,6 @@ int pciGetVirtualFunctionIndex(const char *pf_sysfs_device_link,
int pciDeviceNetName(char *device_link_sysfs_path, char **netname);
+int pciSysfsFile(char **pci_sysfs_device_link, char *pciDeviceName);
+
#endif /* __VIR_PCI_H__ */
--
1.7.4.4
13 years
[libvirt] [PATCH 1/5] Interface pools and passthrough mode patches: Moving the declaration of _pciDevice and _pciDeviceList to pci.h
by Shradha Shah
Interface Pools and Passthrough mode:
Current Method:
The passthrough mode uses a macvtap “direct” connection to connect each guest to the network. The physical interface to be used is picked from among those listed in <interface> sub elements of the <forward> element.
The current specification for <forward> extends to allow 0 or more <interface> sub-elements:
Example:
<forward mode='passthrough' dev='eth10'/>
<interface dev='eth10'/>
<interface dev='eth12'/>
<interface dev='eth18'/>
<interface dev='eth20'/>
</forward>
However with an ethernet card with 64 VF's or more, the above method gets tedious on the system.
On the other hand, just parameterizing a string (eth%d) is inadequate, eg, when there are multiple non-contiguous ranges.
Proposed Method:
The 5 patches provided along with this introductory e-mail
i) Introduce a structure to store the state of all the virtual functions attached to each physical function
ii) Find a free virtual function given the physical function.
The forward specification will hence only mention the physical function as the interface sub element:
Example:
<forward mode='passthrough' dev='eth2'/>
<interface dev='eth2'/>
</forward>
---
src/util/pci.c | 35 -----------------------------------
src/util/pci.h | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 35 deletions(-)
diff --git a/src/util/pci.c b/src/util/pci.c
index cd82b43..857078d 100644
--- a/src/util/pci.c
+++ b/src/util/pci.c
@@ -45,45 +45,10 @@
# define MODPROBE "modprobe"
#endif
-#define PCI_SYSFS "/sys/bus/pci/"
-#define PCI_ID_LEN 10 /* "XXXX XXXX" */
-#define PCI_ADDR_LEN 13 /* "XXXX:XX:XX.X" */
-
#define SRIOV_FOUND 0
#define SRIOV_NOT_FOUND 1
#define SRIOV_ERROR -1
-struct _pciDevice {
- unsigned domain;
- unsigned bus;
- unsigned slot;
- unsigned function;
-
- char name[PCI_ADDR_LEN]; /* domain:bus:slot.function */
- char id[PCI_ID_LEN]; /* product vendor */
- char *path;
- const char *used_by; /* The domain which uses the device */
- int fd;
-
- unsigned initted;
- unsigned pcie_cap_pos;
- unsigned pci_pm_cap_pos;
- unsigned has_flr : 1;
- unsigned has_pm_reset : 1;
- unsigned managed : 1;
-
- /* used by reattach function */
- unsigned unbind_from_stub : 1;
- unsigned remove_slot : 1;
- unsigned reprobe : 1;
-};
-
-struct _pciDeviceList {
- unsigned count;
- pciDevice **devs;
-};
-
-
/* For virReportOOMError() and virReportSystemError() */
#define VIR_FROM_THIS VIR_FROM_NONE
diff --git a/src/util/pci.h b/src/util/pci.h
index 76e37e3..8e47fc2 100644
--- a/src/util/pci.h
+++ b/src/util/pci.h
@@ -24,9 +24,43 @@
# include "internal.h"
+#define PCI_SYSFS "/sys/bus/pci/"
+#define PCI_ID_LEN 10 /* "XXXX XXXX" */
+#define PCI_ADDR_LEN 13 /* "XXXX:XX:XX.X" */
+
typedef struct _pciDevice pciDevice;
typedef struct _pciDeviceList pciDeviceList;
+struct _pciDevice {
+ unsigned domain;
+ unsigned bus;
+ unsigned slot;
+ unsigned function;
+
+ char name[PCI_ADDR_LEN]; /* domain:bus:slot.function */
+ char id[PCI_ID_LEN]; /* product vendor */
+ char *path;
+ const char *used_by; /* The domain which uses the device */
+ int fd;
+
+ unsigned initted;
+ unsigned pcie_cap_pos;
+ unsigned pci_pm_cap_pos;
+ unsigned has_flr : 1;
+ unsigned has_pm_reset : 1;
+ unsigned managed : 1;
+
+ /* used by reattach function */
+ unsigned unbind_from_stub : 1;
+ unsigned remove_slot : 1;
+ unsigned reprobe : 1;
+};
+
+struct _pciDeviceList {
+ unsigned count;
+ pciDevice **devs;
+};
+
struct pci_config_address {
unsigned int domain;
unsigned int bus;
--
1.7.4.4
13 years
[libvirt] [PATCH] util: fix thinko in runIO
by Paolo Bonzini
When aligning you need to clear the bits in the mask and leave the
others aside. Likely this code has never run, and will never run.
Signed-off-by: Paolo Bonzini <pbonzini(a)redhat.com>
---
src/util/iohelper.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/util/iohelper.c b/src/util/iohelper.c
index 9e7bbde..93154f8 100644
--- a/src/util/iohelper.c
+++ b/src/util/iohelper.c
@@ -98,7 +98,7 @@ runIO(const char *path, int fd, int oflags, unsigned long long length)
goto cleanup;
}
base = buf;
- buf = (char *) (((intptr_t) base + alignMask) & alignMask);
+ buf = (char *) (((intptr_t) base + alignMask) & ~alignMask);
#endif
switch (oflags & O_ACCMODE) {
--
1.7.7.1
13 years
[libvirt] [PATCH] storage: Skip socket and fifo on pool-start
by Michal Privoznik
If pool directory contains special files like FIFO or sockets
we want to skip those on pool-start or pool-refresh otherwise
open() will get an error.
---
src/storage/storage_backend.c | 25 ++++++++++++++++---------
1 files changed, 16 insertions(+), 9 deletions(-)
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index 93c98d6..d30829d 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -1013,9 +1013,24 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags)
struct stat sb;
char *base = last_component(path);
+ if (lstat(path, &sb) < 0) {
+ virReportSystemError(errno,
+ _("cannot stat file '%s'"),
+ path);
+ return -1;
+ }
+
+ if (S_ISFIFO(sb.st_mode)) {
+ VIR_WARN("ignoring FIFO '%s'", path);
+ return -2;
+ } else if (S_ISSOCK(sb.st_mode)) {
+ VIR_WARN("ignoring socket '%s'", path);
+ return -2;
+ }
+
if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_NOCTTY)) < 0) {
if ((errno == ENOENT || errno == ELOOP) &&
- lstat(path, &sb) == 0) {
+ S_ISLNK(sb.st_mode)) {
VIR_WARN("ignoring dangling symlink '%s'", path);
return -2;
}
@@ -1026,14 +1041,6 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags)
return -1;
}
- if (fstat(fd, &sb) < 0) {
- virReportSystemError(errno,
- _("cannot stat file '%s'"),
- path);
- VIR_FORCE_CLOSE(fd);
- return -1;
- }
-
if (S_ISREG(sb.st_mode))
mode = VIR_STORAGE_VOL_OPEN_REG;
else if (S_ISCHR(sb.st_mode))
--
1.7.3.4
13 years
[libvirt] ACLs for libvirt
by Michal Privoznik
Hi all,
I'd like to implement this new feature for libvirt. However, I think we
should settle down on design first. My biggest concern is choosing the
right level on on which ACLs will be implemented. Should be interested
only in (user, API), or with more granularity (user, API, API's parameters)?
Or should we take the RBAC path?
How should we even identify and authorize users?
My initial though is to create framework which can be used then to
implement ACLs on any level we want.
What's our opinion?
Michal
13 years