On Tue, Aug 19, 2014 at 09:00:05PM -0500, Christoph Lameter wrote: > On Mon, 18 Aug 2014, Paul E. McKenney wrote: > > > > +#ifdef CONFIG_RCU_DEBUG_XYZ > > > > If you make CONFIG_RCU_DEBUG_XYZ instead be CONFIG_DEBUG_OBJECTS_RCU_HEAD, > > then it will automatically show up when it needs to. > > Ok. > > > The rest looks plausible, for whatever that is worth. > > We talked in the hallway about init_rcu_head not touching > the contents of the rcu_head. If that is the case then we can simplify > the patch. That is correct -- the debug-objects code uses separate storage to track states, and does not touch the memory to which the state applies. > We could also remove the #ifdefs if init_rcu_head and destroy_rcu_head > are no ops if CONFIG_DEBUG_RCU_HEAD is not defined. And indeed they are, good point! It appears to me that both sets of #ifdefs can go away. Thanx, Paul > Index: linux/mm/slub.c > =================================================================== > --- linux.orig/mm/slub.c > +++ linux/mm/slub.c > @@ -1308,6 +1308,25 @@ static inline struct page *alloc_slab_pa > return page; > } > > +#define need_reserve_slab_rcu \ > + (sizeof(((struct page *)NULL)->lru) < sizeof(struct rcu_head)) > + > +static struct rcu_head *get_rcu_head(struct kmem_cache *s, struct page *page) > +{ > + if (need_reserve_slab_rcu) { > + int order = compound_order(page); > + int offset = (PAGE_SIZE << order) - s->reserved; > + > + VM_BUG_ON(s->reserved != sizeof(struct rcu_head)); > + return page_address(page) + offset; > + } else { > + /* > + * RCU free overloads the RCU head over the LRU > + */ > + return (void *)&page->lru; > + } > +} > + > static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) > { > struct page *page; > @@ -1357,6 +1376,22 @@ static struct page *allocate_slab(struct > kmemcheck_mark_unallocated_pages(page, pages); > } > > +#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD > + if (unlikely(s->flags & SLAB_DESTROY_BY_RCU) && page) > + /* > + * Initialize various things. However, this init is > + * not allowed to modify the contents of the rcu head. > + * Allocations are permitted. However, the use of > + * the same cache or another cache with SLAB_RCU_DESTROY > + * set may cause additional recursions. > + * > + * So in order to be safe the slab caches used > + * in init_rcu_head should be restricted to be of the > + * non rcu kind only. > + */ > + init_rcu_head(get_rcu_head(s, page)); > +#endif > + > if (flags & __GFP_WAIT) > local_irq_disable(); > if (!page) > @@ -1452,13 +1487,13 @@ static void __free_slab(struct kmem_cach > memcg_uncharge_slab(s, order); > } > > -#define need_reserve_slab_rcu \ > - (sizeof(((struct page *)NULL)->lru) < sizeof(struct rcu_head)) > - > static void rcu_free_slab(struct rcu_head *h) > { > struct page *page; > > +#ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD > + destroy_rcu_head(h); > +#endif > if (need_reserve_slab_rcu) > page = virt_to_head_page(h); > else > @@ -1469,24 +1504,9 @@ static void rcu_free_slab(struct rcu_hea > > static void free_slab(struct kmem_cache *s, struct page *page) > { > - if (unlikely(s->flags & SLAB_DESTROY_BY_RCU)) { > - struct rcu_head *head; > - > - if (need_reserve_slab_rcu) { > - int order = compound_order(page); > - int offset = (PAGE_SIZE << order) - s->reserved; > - > - VM_BUG_ON(s->reserved != sizeof(*head)); > - head = page_address(page) + offset; > - } else { > - /* > - * RCU free overloads the RCU head over the LRU > - */ > - head = (void *)&page->lru; > - } > - > - call_rcu(head, rcu_free_slab); > - } else > + if (unlikely(s->flags & SLAB_DESTROY_BY_RCU)) > + call_rcu(get_rcu_head(s, page), rcu_free_slab); > + else > __free_slab(s, page); > } > -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>