From: Christoph Lameter Date: Mon, 16 May 2011 20:26:08 +0000 (-0500) Subject: slub: Make CONFIG_DEBUG_PAGE_ALLOC work with new fastpath X-Git-Tag: v2.6.39.1~73 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=440316e6310c2ce372e32d12c83ccc8ddcfb5028;p=karo-tx-linux.git slub: Make CONFIG_DEBUG_PAGE_ALLOC work with new fastpath commit 1393d9a1857471f816d0be1ccc1d6433a86050f6 upstream. Fastpath can do a speculative access to a page that CONFIG_DEBUG_PAGE_ALLOC may have marked as invalid to retrieve the pointer to the next free object. Use probe_kernel_read in that case in order not to cause a page fault. Reported-by: Eric Dumazet Signed-off-by: Christoph Lameter Signed-off-by: Eric Dumazet Signed-off-by: Pekka Enberg Signed-off-by: Greg Kroah-Hartman --- diff --git a/mm/slub.c b/mm/slub.c index 9d2e5e46bf09..f6cb6cd69fcc 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -261,6 +261,18 @@ static inline void *get_freepointer(struct kmem_cache *s, void *object) return *(void **)(object + s->offset); } +static inline void *get_freepointer_safe(struct kmem_cache *s, void *object) +{ + void *p; + +#ifdef CONFIG_DEBUG_PAGEALLOC + probe_kernel_read(&p, (void **)(object + s->offset), sizeof(p)); +#else + p = get_freepointer(s, object); +#endif + return p; +} + static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp) { *(void **)(object + s->offset) = fp; @@ -1943,7 +1955,7 @@ redo: if (unlikely(!irqsafe_cpu_cmpxchg_double( s->cpu_slab->freelist, s->cpu_slab->tid, object, tid, - get_freepointer(s, object), next_tid(tid)))) { + get_freepointer_safe(s, object), next_tid(tid)))) { note_cmpxchg_failure("slab_alloc", s, tid); goto redo;