Received: with ECARTIS (v1.0.0; list netdev); Tue, 05 Apr 2005 11:55:59 -0700 (PDT) Received: from graphe.net (graphe.net [209.204.138.32]) by oss.sgi.com (8.13.0/8.13.0) with ESMTP id j35Itshs028771 for ; Tue, 5 Apr 2005 11:55:54 -0700 Received: from christoph (helo=localhost) by graphe.net with local-esmtp (Exim 4.50) id 1DItDF-0003Zx-I4 for netdev@oss.sgi.com; Tue, 05 Apr 2005 11:55:46 -0700 Date: Tue, 5 Apr 2005 11:55:45 -0700 (PDT) From: Christoph Lameter X-X-Sender: christoph@server.graphe.net To: netdev@oss.sgi.com Subject: atomic_dec_and_test for child dst needed in dst_destroy? Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Virus-Scanned: ClamAV 0.83/808/Tue Apr 5 02:54:46 2005 on oss.sgi.com X-Virus-Status: Clean X-archive-position: 1440 X-ecartis-version: Ecartis v1.0.0 Sender: netdev-bounce@oss.sgi.com Errors-to: netdev-bounce@oss.sgi.com X-original-sender: christoph@lameter.com Precedence: bulk X-list: netdev It seems that the atomic_dec_and_test for the child dst in net/core/dst.c is really not needed since dst_destroy cannot be called simultanously for the same dst (frees dst unconditionally via kmem_cache_free). If a dst can only have one child then the dst may only be deleted from its parent dst. The refcnt is also incremented via dst_hold and decremented via dst_release elsewhere (seems that they may race with dst_destroy?) but there is no provisions to do something special if __refcnt would reach zero in dst_release. __refcnt is always expected to be always greater than zero there. However, it is checked without dec_and_test for zero in various other locations (dst_free, dst_run_gc, dn_dst_check_expire). Is the atomic_dec_and_test in dst_destroy just there to join two atomic operations into one without being necessary for the correctness of freeing dsts? Then we really would not need atomic_dec_and_test in dst_destroy() and the following patch would be safe (There are some ideas for optimizations that would not be able to preserve the atomic_dec_and_test). Index: linux-2.6.11/net/core/dst.c =================================================================== --- linux-2.6.11.orig/net/core/dst.c 2005-03-01 23:38:12.000000000 -0800 +++ linux-2.6.11/net/core/dst.c 2005-04-05 11:04:41.000000000 -0700 @@ -198,7 +198,8 @@ again: dst = child; if (dst) { - if (atomic_dec_and_test(&dst->__refcnt)) { + atomic_dec(&dst->__refcnt); + if (!atomic_read(&dst->__refcnt)) { /* We were real parent of this dst, so kill child. */ if (dst->flags&DST_NOHASH) goto again;