Christoph Lameter a écrit : > On Thu, 3 Sep 2009, Eric Dumazet wrote: > >> Point is we cannot deal with RCU quietness before disposing the slab cache, >> (if SLAB_DESTROY_BY_RCU was set on the cache) since this disposing *will* >> make call_rcu() calls when a full slab is freed/purged. > > There is no need to do call_rcu calls for frees at that point since > objects are no longer in use. We could simply disable SLAB_DESTROY_BY_RCU > for the final clearing of caches. > >> And when RCU grace period is elapsed, the callback *will* need access to >> the cache we want to dismantle. Better to not have kfreed()/poisoned it... > > But going through the RCU period is pointless since no user of the cache > remains. > >> I believe you mix two RCU uses here. >> >> 1) The one we all know, is use normal caches (!SLAB_DESTROY_BY_RCU) >> (or kmalloc()), and use call_rcu(... kfree_something) >> >> In this case, you are 100% right that the subsystem itself has >> to call rcu_barrier() (or respect whatever self-synchro) itself, >> before calling kmem_cache_destroy() >> >> 2) The SLAB_DESTROY_BY_RCU one. >> >> Part of cache dismantle needs to call rcu_barrier() itself. >> Caller doesnt have to use rcu_barrier(). It would be a waste of time, >> as kmem_cache_destroy() will refill rcu wait queues with its own stuff. > > The dismantling does not need RCU since there are no operations on the > objects in progress. So simply switch DESTROY_BY_RCU off for close. > > > --- > mm/slub.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > Index: linux-2.6/mm/slub.c > =================================================================== > --- linux-2.6.orig/mm/slub.c 2009-09-03 10:14:51.000000000 -0500 > +++ linux-2.6/mm/slub.c 2009-09-03 10:18:32.000000000 -0500 > @@ -2594,9 +2594,9 @@ static inline int kmem_cache_close(struc > */ > void kmem_cache_destroy(struct kmem_cache *s) > { > - if (s->flags & SLAB_DESTROY_BY_RCU) > - rcu_barrier(); > down_write(&slub_lock); > + /* Stop deferring frees so that we can immediately free structures */ > + s->flags &= ~SLAB_DESTROY_BY_RCU; > s->refcount--; > if (!s->refcount) { > list_del(&s->list); It seems very smart, but needs review of all callers to make sure no slabs are waiting for final freeing in call_rcu queue on some cpu. I suspect most of them will then have to use rcu_barrier() before calling kmem_cache_destroy(), so why not factorizing code in one place ? net/dccp/ipv6.c:1145: .slab_flags = SLAB_DESTROY_BY_RCU, net/dccp/ipv4.c:941: .slab_flags = SLAB_DESTROY_BY_RCU, net/ipv4/udp.c:1593: .slab_flags = SLAB_DESTROY_BY_RCU, net/ipv4/udplite.c:54: .slab_flags = SLAB_DESTROY_BY_RCU, net/ipv4/tcp_ipv4.c:2446: .slab_flags = SLAB_DESTROY_BY_RCU, net/ipv4/udp.c.orig:1587: .slab_flags = SLAB_DESTROY_BY_RCU, net/ipv6/udp.c:1274: .slab_flags = SLAB_DESTROY_BY_RCU, net/ipv6/udplite.c:52: .slab_flags = SLAB_DESTROY_BY_RCU, net/ipv6/tcp_ipv6.c:2085: .slab_flags = SLAB_DESTROY_BY_RCU, net/netfilter/nf_conntrack_core.c:1269: 0, SLAB_DESTROY_BY_RCU, NULL); -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html