[libvirt] [PATCH 3/3] virNWFilterBindingObjListAddLocked: Produce better error message than 'Duplicate key'

Michal Privoznik posted 3 patches 6 years, 10 months ago
[libvirt] [PATCH 3/3] virNWFilterBindingObjListAddLocked: Produce better error message than 'Duplicate key'
Posted by Michal Privoznik 6 years, 10 months ago
If there are two concurrent threads, one of which is removing an
nwfilter from the list and the other is trying to add it back they
may serialize in the following order:

1) obj->removing is set and @obj is unlocked.
2) The tread that's trying to add the nwfilter onto the list locks
   the list and tries to find, if the nwfilter already exists.
3) Our lookup functions say it doesn't, so the thread proceeds to
   virHashAddEntry() which fails with 'Duplicate key' error.

This is obviously not helpful error message at all.

The problem lies in our lookup function
(virNWFilterBindingObjListFindByPortDevLocked()) which return
NULL even if the object is still on the list. They do this so
that the object is not mistakenly looked up by some API. The fix
consists of moving 'removing' check one level up and thus
allowing virNWFilterBindingObjListAddLocked() to produce
meaningful error message.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
 src/conf/virnwfilterbindingobjlist.c | 29 +++++++++++++++++-----------
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/src/conf/virnwfilterbindingobjlist.c b/src/conf/virnwfilterbindingobjlist.c
index 06ccbf53af..dbeee0d55e 100644
--- a/src/conf/virnwfilterbindingobjlist.c
+++ b/src/conf/virnwfilterbindingobjlist.c
@@ -91,14 +91,9 @@ virNWFilterBindingObjListFindByPortDevLocked(virNWFilterBindingObjListPtr bindin
     virNWFilterBindingObjPtr obj;
 
     obj = virHashLookup(bindings->objs, name);
-    virObjectRef(obj);
     if (obj) {
+        virObjectRef(obj);
         virObjectLock(obj);
-        if (virNWFilterBindingObjGetRemoving(obj)) {
-            virObjectUnlock(obj);
-            virObjectUnref(obj);
-            obj = NULL;
-        }
     }
     return obj;
 }
@@ -122,6 +117,12 @@ virNWFilterBindingObjListFindByPortDev(virNWFilterBindingObjListPtr bindings,
     obj = virNWFilterBindingObjListFindByPortDevLocked(bindings, name);
     virObjectRWUnlock(bindings);
 
+    if (obj && virNWFilterBindingObjGetRemoving(obj)) {
+        virObjectUnlock(obj);
+        virObjectUnref(obj);
+        obj = NULL;
+    }
+
     return obj;
 }
 
@@ -169,11 +170,17 @@ virNWFilterBindingObjListAddLocked(virNWFilterBindingObjListPtr bindings,
     virNWFilterBindingObjPtr binding;
 
     /* See if a binding with matching portdev already exists */
-    if ((binding = virNWFilterBindingObjListFindByPortDevLocked(
-             bindings, def->portdevname))) {
-        virReportError(VIR_ERR_OPERATION_FAILED,
-                       _("binding '%s' already exists"),
-                       def->portdevname);
+    binding = virNWFilterBindingObjListFindByPortDevLocked(bindings, def->portdevname);
+    if (binding) {
+        if (virNWFilterBindingObjGetRemoving(binding)) {
+            virReportError(VIR_ERR_OPERATION_FAILED,
+                           _("binding '%s' is already being removed"),
+                           def->portdevname);
+        } else {
+            virReportError(VIR_ERR_OPERATION_FAILED,
+                           _("binding '%s' already exists"),
+                           def->portdevname);
+        }
         goto error;
     }
 
-- 
2.19.2

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
Re: [libvirt] [PATCH 3/3] virNWFilterBindingObjListAddLocked: Produce better error message than 'Duplicate key'
Posted by Cole Robinson 6 years, 10 months ago
On 3/19/19 9:49 AM, Michal Privoznik wrote:
> If there are two concurrent threads, one of which is removing an
> nwfilter from the list and the other is trying to add it back they
> may serialize in the following order:
> 
> 1) obj->removing is set and @obj is unlocked.
> 2) The tread that's trying to add the nwfilter onto the list locks
>    the list and tries to find, if the nwfilter already exists.
> 3) Our lookup functions say it doesn't, so the thread proceeds to
>    virHashAddEntry() which fails with 'Duplicate key' error.
> 
> This is obviously not helpful error message at all.
> 
> The problem lies in our lookup function
> (virNWFilterBindingObjListFindByPortDevLocked()) which return
> NULL even if the object is still on the list. They do this so
> that the object is not mistakenly looked up by some API. The fix
> consists of moving 'removing' check one level up and thus
> allowing virNWFilterBindingObjListAddLocked() to produce
> meaningful error message.
> 
> Signed-off-by: Michal Privoznik <mprivozn@redhat.com>

Reviewed-by: Cole Robinson <crobinso@redhat.com>

- Cole

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list