[libvirt] [PATCH] nwfilter: Fix the test for the result of atomic dec and test

Martin Kletzander mkletzan at redhat.com
Wed Mar 19 13:13:51 UTC 2014


On Tue, Mar 18, 2014 at 09:45:14PM -0400, Stefan Berger wrote:
> From: Stefan Berger <stefanb at linux.vnet.ibm.com>
>
> https://bugzilla.redhat.com/show_bug.cgi?id=1071181
>
> Commit 49b59a15 fixed one problem but masks another one related to pointer
> freeing.
>
> Use virAtomicIntGet() to test for 0 rather than trying to test for 'true'
> after  virAtomicIntDecAndTest().
>
> Avoid putting of the virNWFilterSnoopReq once the thread has been started.
>
> Signed-off-by: Stefan Berger <stefanb at linux.vnet.ibm.com>
> ---
>  src/nwfilter/nwfilter_dhcpsnoop.c | 11 +++++++++--
>  1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/src/nwfilter/nwfilter_dhcpsnoop.c b/src/nwfilter/nwfilter_dhcpsnoop.c
> index d2a8062..32ca304 100644
> --- a/src/nwfilter/nwfilter_dhcpsnoop.c
> +++ b/src/nwfilter/nwfilter_dhcpsnoop.c
> @@ -720,7 +720,10 @@ virNWFilterSnoopReqPut(virNWFilterSnoopReqPtr req)
>
>      virNWFilterSnoopLock();
>
> -    if (virAtomicIntDecAndTest(&req->refctr)) {
> +    virAtomicIntDecAndTest(&req->refctr);
> +
> +    /* make sure it's 0; virAtomitIntDecAndTest may return true on '1' */
> +    if (virAtomicIntGet(&req->refctr) == 0) {

NACK, using two atomic functions, you are making this non-atomic.
between these two atomic operations many things can happen an it's not
what you want I bet.  The virAtomicIntDecAndTest() uses
__sync_fetch_and_sub(atomic, 1) and compares it to 1, that's true, but
since it is fetch_and_sub (and not the other way around, the value
being compared to 1 is the value that the atomic had before it was
decremented.  That means it returns 1 (true) if and only if the
current value is 0.  virAtomicIntDecAndTest() is what you really want
and should use here.

Martin

>          /*
>           * delete the request:
>           * - if we don't find req on the global list anymore
> @@ -1605,6 +1608,7 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver,
>      int tmp;
>      virThread thread;
>      virNWFilterVarValuePtr dhcpsrvrs;
> +    bool threadPuts = false;
>
>      virNWFilterSnoopIFKeyFMT(ifkey, vmuuid, macaddr);
>
> @@ -1690,6 +1694,8 @@ virNWFilterDHCPSnoopReq(virNWFilterTechDriverPtr techdriver,
>      /* prevent thread from holding req */
>      virNWFilterSnoopReqLock(req);
>
> +    threadPuts = true;
> +
>      if (virThreadCreate(&thread, false, virNWFilterDHCPSnoopThread,
>                          req) != 0) {
>          virReportError(VIR_ERR_INTERNAL_ERROR,
> @@ -1737,7 +1743,8 @@ exit_rem_ifnametokey:
>  exit_snoopunlock:
>      virNWFilterSnoopUnlock();
>  exit_snoopreqput:
> -    virNWFilterSnoopReqPut(req);
> +    if (!threadPuts)
> +        virNWFilterSnoopReqPut(req);
>
>      return -1;
>  }
> --
> 1.8.1.4
>
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20140319/257f9e91/attachment-0001.sig>


More information about the libvir-list mailing list