From: Michal Privoznik <mprivozn@redhat.com> Adding a storage volume into a pool is done by calling virStoragePoolObjAddVol(). This function may fail if another volume already exists with the same key/name/target. In some cases the storage driver does check for duplicates before calling the function. But in some cases (e.g. when refreshing an RBD pool in virStorageBackendRBDRefreshPool()) it doesn't. The problem here is that the function reports no error upon failure and leaves it as an exercise for caller. Well, no caller does that. Therefore, make the function report an error. The advantage of this approach is - the function can report more accurate error message than any caller ever could. NB¸ this stems from a discussion on the users list [1], and while this does NOT solve the original issue, it fixes one of the symptoms. 1: https://lists.libvirt.org/archives/list/users@lists.libvirt.org/message/BALV... Signed-off-by: Michal Privoznik <mprivozn@redhat.com> --- This can be very easily reproduced with test driver. No need for ceph. Just duplicate a volume in a custom test driver XML. Before this patch you'd get: error: failed to connect to the hypervisor error: An error occurred, but the cause is unknown After: error: failed to connect to the hypervisor error: operation failed: volume with target path '/dev/disk/by-path/pci-0000:00:17.0-ata-30' already exist src/conf/virstorageobj.c | 45 +++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/src/conf/virstorageobj.c b/src/conf/virstorageobj.c index 59fa5da372..ac79ff4c26 100644 --- a/src/conf/virstorageobj.c +++ b/src/conf/virstorageobj.c @@ -621,19 +621,44 @@ virStoragePoolObjAddVol(virStoragePoolObj *obj, virStorageVolObj *volobj = NULL; virStorageVolObjList *volumes = obj->volumes; + if (!voldef->key) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("volume is missing key")); + return -1; + } + if (!voldef->name) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("volume is missing name")); + return -1; + } + if (!voldef->target.path) { + virReportError(VIR_ERR_OPERATION_FAILED, "%s", + _("volume is missing target path")); + return -1; + } + virObjectRWLockWrite(volumes); - if (!voldef->key || !voldef->name || !voldef->target.path || - g_hash_table_contains(volumes->objsKey, voldef->key) || - g_hash_table_contains(volumes->objsName, voldef->name) || - g_hash_table_contains(volumes->objsPath, voldef->target.path)) { - virObjectRWUnlock(volumes); - return -1; + if (g_hash_table_contains(volumes->objsKey, voldef->key)) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("volume with key '%1$s' already exist"), + voldef->key); + goto error; + } + if (g_hash_table_contains(volumes->objsName, voldef->name)) { + virReportError(VIR_ERR_STORAGE_VOL_EXIST, + _("'%1$s'"), voldef->name); + goto error; + } + if (g_hash_table_contains(volumes->objsPath, voldef->target.path)) { + virReportError(VIR_ERR_OPERATION_FAILED, + _("volume with target path '%1$s' already exist"), + voldef->target.path); + goto error; } if (!(volobj = virStorageVolObjNew())) { - virObjectRWUnlock(volumes); - return -1; + goto error; } VIR_WITH_OBJECT_LOCK_GUARD(volobj) { @@ -652,6 +677,10 @@ virStoragePoolObjAddVol(virStoragePoolObj *obj, virObjectUnref(volobj); virObjectRWUnlock(volumes); return 0; + + error: + virObjectRWUnlock(volumes); + return -1; } -- 2.52.0