From 5a1f2728754a7b7bea4efd245d7171ab6286d681 Mon Sep 17 00:00:00 2001 From: Lei Li Date: Mon, 5 Sep 2011 15:52:03 +0800 Subject: [PATCH] Check for source conflicts in storage pools Fix bug #611823 storage driver should prohibit pools with duplicate underlying storage. Add internal API virStoragePoolSourceFindDuplicate() to do uniqueness check based on source location infomation for pool type. * AUTHORS: add Lei Li --- AUTHORS | 1 + src/conf/storage_conf.c | 80 ++++++++++++++++++++++++++++++++++++ src/conf/storage_conf.h | 5 +++ src/libvirt_private.syms | 2 + src/storage/storage_driver.c | 6 +++ 5 files changed, 94 insertions(+) diff --git a/AUTHORS b/AUTHORS index faec2182f9..dcbb711e2f 100644 --- a/AUTHORS +++ b/AUTHORS @@ -193,6 +193,7 @@ Patches have also been contributed by: Shradha Shah Steve Hodgson Xu He Jie + Lei Li [....send patches to get your name here....] diff --git a/src/conf/storage_conf.c b/src/conf/storage_conf.c index 8d14e872ca..1e7da69345 100644 --- a/src/conf/storage_conf.c +++ b/src/conf/storage_conf.c @@ -1311,6 +1311,21 @@ virStoragePoolObjFindByName(virStoragePoolObjListPtr pools, return NULL; } +virStoragePoolObjPtr +virStoragePoolSourceFindDuplicateDevices(virStoragePoolObjPtr pool, + virStoragePoolDefPtr def) { + unsigned int i, j; + + for (i = 0; i < pool->def->source.ndevice; i++) { + for (j = 0; j < def->source.ndevice; j++) { + if (STREQ(pool->def->source.devices[i].path, def->source.devices[j].path)) + return pool; + } + } + + return NULL; +} + void virStoragePoolObjClearVols(virStoragePoolObjPtr pool) { @@ -1701,6 +1716,71 @@ cleanup: return ret; } +int virStoragePoolSourceFindDuplicate(virStoragePoolObjListPtr pools, + virStoragePoolDefPtr def) +{ + int i; + int ret = 1; + virStoragePoolObjPtr pool = NULL; + virStoragePoolObjPtr matchpool = NULL; + + /* Check the pool list for duplicate underlying storage */ + for (i = 0; i < pools->count; i++) { + pool = pools->objs[i]; + if (def->type != pool->def->type) + continue; + + virStoragePoolObjLock(pool); + + switch (pool->def->type) { + case VIR_STORAGE_POOL_DIR: + if (STREQ(pool->def->target.path, def->target.path)) + matchpool = pool; + break; + case VIR_STORAGE_POOL_NETFS: + if ((STREQ(pool->def->source.dir, def->source.dir)) \ + && (STREQ(pool->def->source.host.name, def->source.host.name))) + matchpool = pool; + break; + case VIR_STORAGE_POOL_SCSI: + if (STREQ(pool->def->source.adapter, def->source.adapter)) + matchpool = pool; + break; + case VIR_STORAGE_POOL_ISCSI: + { + matchpool = virStoragePoolSourceFindDuplicateDevices(pool, def); + if (matchpool) { + if (STREQ(matchpool->def->source.host.name, def->source.host.name)) { + if ((matchpool->def->source.initiator.iqn) && (def->source.initiator.iqn)) { + if (STREQ(matchpool->def->source.initiator.iqn, def->source.initiator.iqn)) + break; + matchpool = NULL; + } + break; + } + matchpool = NULL; + } + break; + } + case VIR_STORAGE_POOL_FS: + case VIR_STORAGE_POOL_LOGICAL: + case VIR_STORAGE_POOL_DISK: + matchpool = virStoragePoolSourceFindDuplicateDevices(pool, def); + break; + default: + break; + } + virStoragePoolObjUnlock(pool); + } + + if (matchpool) { + virStorageReportError(VIR_ERR_OPERATION_FAILED, + _("Storage source conflict with pool: '%s'"), + matchpool->def->name); + ret = -1; + } + return ret; +} void virStoragePoolObjLock(virStoragePoolObjPtr obj) { diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h index 271441a955..d115a15205 100644 --- a/src/conf/storage_conf.h +++ b/src/conf/storage_conf.h @@ -335,6 +335,8 @@ virStoragePoolObjPtr virStoragePoolObjFindByUUID(virStoragePoolObjListPtr pools, const unsigned char *uuid); virStoragePoolObjPtr virStoragePoolObjFindByName(virStoragePoolObjListPtr pools, const char *name); +virStoragePoolObjPtr virStoragePoolSourceFindDuplicateDevices(virStoragePoolObjPtr pool, + virStoragePoolDefPtr def); virStorageVolDefPtr virStorageVolDefFindByKey(virStoragePoolObjPtr pool, const char *key); @@ -388,6 +390,9 @@ int virStoragePoolObjIsDuplicate(virStoragePoolObjListPtr pools, virStoragePoolDefPtr def, unsigned int check_active); +int virStoragePoolSourceFindDuplicate(virStoragePoolObjListPtr pools, + virStoragePoolDefPtr def); + void virStoragePoolObjLock(virStoragePoolObjPtr obj); void virStoragePoolObjUnlock(virStoragePoolObjPtr obj); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 52fc06d7c0..011f7522d0 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -956,7 +956,9 @@ virStoragePoolObjClearVols; virStoragePoolObjDeleteDef; virStoragePoolObjFindByName; virStoragePoolObjFindByUUID; +virStoragePoolSourceFindDuplicateDevices; virStoragePoolObjIsDuplicate; +virStoragePoolSourceFindDuplicate; virStoragePoolObjListFree; virStoragePoolObjLock; virStoragePoolObjRemove; diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 68cac1fc47..c05b74ebf6 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -536,6 +536,9 @@ storagePoolCreate(virConnectPtr conn, if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0) goto cleanup; + if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0) + goto cleanup; + if ((backend = virStorageBackendForType(def->type)) == NULL) goto cleanup; @@ -589,6 +592,9 @@ storagePoolDefine(virConnectPtr conn, if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0) goto cleanup; + if (virStoragePoolSourceFindDuplicate(&driver->pools, def) < 0) + goto cleanup; + if (virStorageBackendForType(def->type) == NULL) goto cleanup;