From afc0cedbe9138e3e8b38bfa1e4dfd01a2c537d62 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 16 May 2007 22:10:49 -0700 Subject: [PATCH 01/34] slob: implement RCU freeing The SLOB allocator should implement SLAB_DESTROY_BY_RCU correctly, because even on UP, RCU freeing semantics are not equivalent to simply freeing immediately. This also allows SLOB to be used on SMP. Signed-off-by: Nick Piggin Acked-by: Matt Mackall Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/Kconfig | 7 ++----- mm/slob.c | 52 +++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/init/Kconfig b/init/Kconfig index 4e009fde4b695..9264895ab331a 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -577,14 +577,11 @@ config SLUB and has enhanced diagnostics. config SLOB -# -# SLOB does not support SMP because SLAB_DESTROY_BY_RCU is unsupported -# - depends on EMBEDDED && !SMP && !SPARSEMEM + depends on EMBEDDED && !SPARSEMEM bool "SLOB (Simple Allocator)" help SLOB replaces the SLAB allocator with a drastically simpler - allocator. SLOB is more space efficient that SLAB but does not + allocator. SLOB is more space efficient than SLAB but does not scale well (single lock for all operations) and is also highly susceptible to fragmentation. SLUB can accomplish a higher object density. It is usually better to use SLUB instead of SLOB. diff --git a/mm/slob.c b/mm/slob.c index c6933bc19bcd8..57bb72ed0d468 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -35,6 +35,7 @@ #include #include #include +#include struct slob_block { int units; @@ -53,6 +54,16 @@ struct bigblock { }; typedef struct bigblock bigblock_t; +/* + * struct slob_rcu is inserted at the tail of allocated slob blocks, which + * were created with a SLAB_DESTROY_BY_RCU slab. slob_rcu is used to free + * the block using call_rcu. + */ +struct slob_rcu { + struct rcu_head head; + int size; +}; + static slob_t arena = { .next = &arena, .units = 1 }; static slob_t *slobfree = &arena; static bigblock_t *bigblocks; @@ -266,6 +277,7 @@ size_t ksize(const void *block) struct kmem_cache { unsigned int size, align; + unsigned long flags; const char *name; void (*ctor)(void *, struct kmem_cache *, unsigned long); void (*dtor)(void *, struct kmem_cache *, unsigned long); @@ -283,6 +295,12 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, if (c) { c->name = name; c->size = size; + if (flags & SLAB_DESTROY_BY_RCU) { + BUG_ON(dtor); + /* leave room for rcu footer at the end of object */ + c->size += sizeof(struct slob_rcu); + } + c->flags = flags; c->ctor = ctor; c->dtor = dtor; /* ignore alignment unless it's forced */ @@ -328,15 +346,35 @@ void *kmem_cache_zalloc(struct kmem_cache *c, gfp_t flags) } EXPORT_SYMBOL(kmem_cache_zalloc); -void kmem_cache_free(struct kmem_cache *c, void *b) +static void __kmem_cache_free(void *b, int size) { - if (c->dtor) - c->dtor(b, c, 0); - - if (c->size < PAGE_SIZE) - slob_free(b, c->size); + if (size < PAGE_SIZE) + slob_free(b, size); else - free_pages((unsigned long)b, get_order(c->size)); + free_pages((unsigned long)b, get_order(size)); +} + +static void kmem_rcu_free(struct rcu_head *head) +{ + struct slob_rcu *slob_rcu = (struct slob_rcu *)head; + void *b = (void *)slob_rcu - (slob_rcu->size - sizeof(struct slob_rcu)); + + __kmem_cache_free(b, slob_rcu->size); +} + +void kmem_cache_free(struct kmem_cache *c, void *b) +{ + if (unlikely(c->flags & SLAB_DESTROY_BY_RCU)) { + struct slob_rcu *slob_rcu; + slob_rcu = b + (c->size - sizeof(struct slob_rcu)); + INIT_RCU_HEAD(&slob_rcu->head); + slob_rcu->size = c->size; + call_rcu(&slob_rcu->head, kmem_rcu_free); + } else { + if (c->dtor) + c->dtor(b, c, 0); + __kmem_cache_free(b, c->size); + } } EXPORT_SYMBOL(kmem_cache_free); From c59def9f222d44bb7e2f0a559f2906191a0862d7 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 16 May 2007 22:10:50 -0700 Subject: [PATCH 02/34] Slab allocators: Drop support for destructors There is no user of destructors left. There is no reason why we should keep checking for destructors calls in the slab allocators. The RFC for this patch was discussed at http://marc.info/?l=linux-kernel&m=117882364330705&w=2 Destructors were mainly used for list management which required them to take a spinlock. Taking a spinlock in a destructor is a bit risky since the slab allocators may run the destructors anytime they decide a slab is no longer needed. Patch drops destructor support. Any attempt to use a destructor will BUG(). Acked-by: Pekka Enberg Acked-by: Paul Mundt Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/slub_def.h | 1 - mm/slab.c | 27 ++---------------------- mm/slob.c | 5 ----- mm/slub.c | 45 +++++++++++++--------------------------- 4 files changed, 16 insertions(+), 62 deletions(-) diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index c6c1f4a120e3a..5e2e7297dfaaa 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -40,7 +40,6 @@ struct kmem_cache { int objects; /* Number of objects in slab */ int refcount; /* Refcount for slab cache destroy */ void (*ctor)(void *, struct kmem_cache *, unsigned long); - void (*dtor)(void *, struct kmem_cache *, unsigned long); int inuse; /* Offset to metadata */ int align; /* Alignment */ const char *name; /* Name (only for display!) */ diff --git a/mm/slab.c b/mm/slab.c index 944b20581f8c4..12344432e201f 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -409,9 +409,6 @@ struct kmem_cache { /* constructor func */ void (*ctor) (void *, struct kmem_cache *, unsigned long); - /* de-constructor func */ - void (*dtor) (void *, struct kmem_cache *, unsigned long); - /* 5) cache creation/removal */ const char *name; struct list_head next; @@ -1911,20 +1908,11 @@ static void slab_destroy_objs(struct kmem_cache *cachep, struct slab *slabp) slab_error(cachep, "end of a freed object " "was overwritten"); } - if (cachep->dtor && !(cachep->flags & SLAB_POISON)) - (cachep->dtor) (objp + obj_offset(cachep), cachep, 0); } } #else static void slab_destroy_objs(struct kmem_cache *cachep, struct slab *slabp) { - if (cachep->dtor) { - int i; - for (i = 0; i < cachep->num; i++) { - void *objp = index_to_obj(cachep, slabp, i); - (cachep->dtor) (objp, cachep, 0); - } - } } #endif @@ -2124,7 +2112,7 @@ static int setup_cpu_cache(struct kmem_cache *cachep) * @align: The required alignment for the objects. * @flags: SLAB flags * @ctor: A constructor for the objects. - * @dtor: A destructor for the objects. + * @dtor: A destructor for the objects (not implemented anymore). * * Returns a ptr to the cache on success, NULL on failure. * Cannot be called within a int, but can be interrupted. @@ -2159,7 +2147,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, * Sanity checks... these are all serious usage bugs. */ if (!name || in_interrupt() || (size < BYTES_PER_WORD) || - (size > (1 << MAX_OBJ_ORDER) * PAGE_SIZE) || (dtor && !ctor)) { + (size > (1 << MAX_OBJ_ORDER) * PAGE_SIZE) || dtor) { printk(KERN_ERR "%s: Early error in slab %s\n", __FUNCTION__, name); BUG(); @@ -2213,9 +2201,6 @@ kmem_cache_create (const char *name, size_t size, size_t align, if (flags & SLAB_DESTROY_BY_RCU) BUG_ON(flags & SLAB_POISON); #endif - if (flags & SLAB_DESTROY_BY_RCU) - BUG_ON(dtor); - /* * Always checks flags, a caller might be expecting debug support which * isn't available. @@ -2370,7 +2355,6 @@ kmem_cache_create (const char *name, size_t size, size_t align, BUG_ON(!cachep->slabp_cache); } cachep->ctor = ctor; - cachep->dtor = dtor; cachep->name = name; if (setup_cpu_cache(cachep)) { @@ -2835,7 +2819,6 @@ static int cache_grow(struct kmem_cache *cachep, * Perform extra freeing checks: * - detect bad pointers. * - POISON/RED_ZONE checking - * - destructor calls, for caches with POISON+dtor */ static void kfree_debugcheck(const void *objp) { @@ -2894,12 +2877,6 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, BUG_ON(objnr >= cachep->num); BUG_ON(objp != index_to_obj(cachep, slabp, objnr)); - if (cachep->flags & SLAB_POISON && cachep->dtor) { - /* we want to cache poison the object, - * call the destruction callback - */ - cachep->dtor(objp + obj_offset(cachep), cachep, 0); - } #ifdef CONFIG_DEBUG_SLAB_LEAK slab_bufctl(slabp)[objnr] = BUFCTL_FREE; #endif diff --git a/mm/slob.c b/mm/slob.c index 57bb72ed0d468..79164a4f54ad2 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -280,7 +280,6 @@ struct kmem_cache { unsigned long flags; const char *name; void (*ctor)(void *, struct kmem_cache *, unsigned long); - void (*dtor)(void *, struct kmem_cache *, unsigned long); }; struct kmem_cache *kmem_cache_create(const char *name, size_t size, @@ -296,13 +295,11 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, c->name = name; c->size = size; if (flags & SLAB_DESTROY_BY_RCU) { - BUG_ON(dtor); /* leave room for rcu footer at the end of object */ c->size += sizeof(struct slob_rcu); } c->flags = flags; c->ctor = ctor; - c->dtor = dtor; /* ignore alignment unless it's forced */ c->align = (flags & SLAB_HWCACHE_ALIGN) ? SLOB_ALIGN : 0; if (c->align < align) @@ -371,8 +368,6 @@ void kmem_cache_free(struct kmem_cache *c, void *b) slob_rcu->size = c->size; call_rcu(&slob_rcu->head, kmem_rcu_free); } else { - if (c->dtor) - c->dtor(b, c, 0); __kmem_cache_free(b, c->size); } } diff --git a/mm/slub.c b/mm/slub.c index 5e3e8bc9838f8..022c1b4d74d4d 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -891,13 +891,13 @@ static void kmem_cache_open_debug_check(struct kmem_cache *s) * On 32 bit platforms the limit is 256k. On 64bit platforms * the limit is 512k. * - * Debugging or ctor/dtors may create a need to move the free + * Debugging or ctor may create a need to move the free * pointer. Fail if this happens. */ if (s->size >= 65535 * sizeof(void *)) { BUG_ON(s->flags & (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | SLAB_DESTROY_BY_RCU)); - BUG_ON(s->ctor || s->dtor); + BUG_ON(s->ctor); } else /* @@ -1030,15 +1030,12 @@ static void __free_slab(struct kmem_cache *s, struct page *page) { int pages = 1 << s->order; - if (unlikely(SlabDebug(page) || s->dtor)) { + if (unlikely(SlabDebug(page))) { void *p; slab_pad_check(s, page); - for_each_object(p, s, page_address(page)) { - if (s->dtor) - s->dtor(p, s, 0); + for_each_object(p, s, page_address(page)) check_object(s, page, p, 0); - } } mod_zone_page_state(page_zone(page), @@ -1871,7 +1868,7 @@ static int calculate_sizes(struct kmem_cache *s) * then we should never poison the object itself. */ if ((flags & SLAB_POISON) && !(flags & SLAB_DESTROY_BY_RCU) && - !s->ctor && !s->dtor) + !s->ctor) s->flags |= __OBJECT_POISON; else s->flags &= ~__OBJECT_POISON; @@ -1901,7 +1898,7 @@ static int calculate_sizes(struct kmem_cache *s) #ifdef CONFIG_SLUB_DEBUG if (((flags & (SLAB_DESTROY_BY_RCU | SLAB_POISON)) || - s->ctor || s->dtor)) { + s->ctor)) { /* * Relocate free pointer after the object if it is not * permitted to overwrite the first word of the object on @@ -1970,13 +1967,11 @@ static int calculate_sizes(struct kmem_cache *s) static int kmem_cache_open(struct kmem_cache *s, gfp_t gfpflags, const char *name, size_t size, size_t align, unsigned long flags, - void (*ctor)(void *, struct kmem_cache *, unsigned long), - void (*dtor)(void *, struct kmem_cache *, unsigned long)) + void (*ctor)(void *, struct kmem_cache *, unsigned long)) { memset(s, 0, kmem_size); s->name = name; s->ctor = ctor; - s->dtor = dtor; s->objsize = size; s->flags = flags; s->align = align; @@ -2161,7 +2156,7 @@ static struct kmem_cache *create_kmalloc_cache(struct kmem_cache *s, down_write(&slub_lock); if (!kmem_cache_open(s, gfp_flags, name, size, ARCH_KMALLOC_MINALIGN, - flags, NULL, NULL)) + flags, NULL)) goto panic; list_add(&s->list, &slab_caches); @@ -2463,7 +2458,7 @@ static int slab_unmergeable(struct kmem_cache *s) if (slub_nomerge || (s->flags & SLUB_NEVER_MERGE)) return 1; - if (s->ctor || s->dtor) + if (s->ctor) return 1; return 0; @@ -2471,15 +2466,14 @@ static int slab_unmergeable(struct kmem_cache *s) static struct kmem_cache *find_mergeable(size_t size, size_t align, unsigned long flags, - void (*ctor)(void *, struct kmem_cache *, unsigned long), - void (*dtor)(void *, struct kmem_cache *, unsigned long)) + void (*ctor)(void *, struct kmem_cache *, unsigned long)) { struct list_head *h; if (slub_nomerge || (flags & SLUB_NEVER_MERGE)) return NULL; - if (ctor || dtor) + if (ctor) return NULL; size = ALIGN(size, sizeof(void *)); @@ -2521,8 +2515,9 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, { struct kmem_cache *s; + BUG_ON(dtor); down_write(&slub_lock); - s = find_mergeable(size, align, flags, ctor, dtor); + s = find_mergeable(size, align, flags, ctor); if (s) { s->refcount++; /* @@ -2536,7 +2531,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, } else { s = kmalloc(kmem_size, GFP_KERNEL); if (s && kmem_cache_open(s, GFP_KERNEL, name, - size, align, flags, ctor, dtor)) { + size, align, flags, ctor)) { if (sysfs_slab_add(s)) { kfree(s); goto err; @@ -3177,17 +3172,6 @@ static ssize_t ctor_show(struct kmem_cache *s, char *buf) } SLAB_ATTR_RO(ctor); -static ssize_t dtor_show(struct kmem_cache *s, char *buf) -{ - if (s->dtor) { - int n = sprint_symbol(buf, (unsigned long)s->dtor); - - return n + sprintf(buf + n, "\n"); - } - return 0; -} -SLAB_ATTR_RO(dtor); - static ssize_t aliases_show(struct kmem_cache *s, char *buf) { return sprintf(buf, "%d\n", s->refcount - 1); @@ -3419,7 +3403,6 @@ static struct attribute * slab_attrs[] = { &partial_attr.attr, &cpu_slabs_attr.attr, &ctor_attr.attr, - &dtor_attr.attr, &aliases_attr.attr, &align_attr.attr, &sanity_checks_attr.attr, From 9fbf09a09e8aa50c56e2c6dfacc27eff93ff4c93 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 16 May 2007 22:10:51 -0700 Subject: [PATCH 03/34] SLUB: Remove depends on EXPERIMENTAL and !ARCH_USES_SLAB_PAGE_STRUCT No arch sets ARCH_USES_SLAB_PAGE_STRUCT anymore. Remove the experimental dependency as well since we want to have it as a real alternative to SLAB. It all comes down to killing a single line from init/Kconfig. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/init/Kconfig b/init/Kconfig index 9264895ab331a..a9e99f8328ff4 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -567,7 +567,6 @@ config SLAB a slab allocator. config SLUB - depends on EXPERIMENTAL && !ARCH_USES_SLAB_PAGE_STRUCT bool "SLUB (Unqueued Allocator)" help SLUB is a slab allocator that minimizes cache line usage From 3ca12ee549f7837b8a685dddc9515f9fc28434ee Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 16 May 2007 22:10:52 -0700 Subject: [PATCH 04/34] SLAB: Move two remaining SLAB specific definitions to slab_def.h Two definitions remained in slab.h that are particular to the SLAB allocator. Move to slab_def.h Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/slab.h | 3 --- include/linux/slab_def.h | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/slab.h b/include/linux/slab.h index 71829efc40ba2..5dbc0bae26e36 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -233,9 +233,6 @@ extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, void *); #endif /* DEBUG_SLAB */ -extern const struct seq_operations slabinfo_op; -ssize_t slabinfo_write(struct file *, const char __user *, size_t, loff_t *); - #endif /* __KERNEL__ */ #endif /* _LINUX_SLAB_H */ diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index 5e4364644ed13..8d81a60518e4c 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -109,4 +109,7 @@ static inline void *kmalloc_node(size_t size, gfp_t flags, int node) #endif /* CONFIG_NUMA */ +extern const struct seq_operations slabinfo_op; +ssize_t slabinfo_write(struct file *, const char __user *, size_t, loff_t *); + #endif /* _LINUX_SLAB_DEF_H */ From 4b6f0750457db1f573eb6226960a432da3be8fe2 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 16 May 2007 22:10:53 -0700 Subject: [PATCH 05/34] SLUB: Define functions for cpu slab handling instead of using PageActive Use inline functions to access the per cpu bit. Intoduce the notion of "freezing" a slab to make things more understandable. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slub.c | 57 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 19 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index 022c1b4d74d4d..ce96d485a88f9 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -78,10 +78,18 @@ * * Overloading of page flags that are otherwise used for LRU management. * - * PageActive The slab is used as a cpu cache. Allocations - * may be performed from the slab. The slab is not - * on any slab list and cannot be moved onto one. - * The cpu slab may be equipped with an additioanl + * PageActive The slab is frozen and exempt from list processing. + * This means that the slab is dedicated to a purpose + * such as satisfying allocations for a specific + * processor. Objects may be freed in the slab while + * it is frozen but slab_free will then skip the usual + * list operations. It is up to the processor holding + * the slab to integrate the slab into the slab lists + * when the slab is no longer needed. + * + * One use of this flag is to mark slabs that are + * used for allocations. Then such a slab becomes a cpu + * slab. The cpu slab may be equipped with an additional * lockless_freelist that allows lockless access to * free objects in addition to the regular freelist * that requires the slab lock. @@ -91,6 +99,21 @@ * the fast path and disables lockless freelists. */ +static inline int SlabFrozen(struct page *page) +{ + return PageActive(page); +} + +static inline void SetSlabFrozen(struct page *page) +{ + SetPageActive(page); +} + +static inline void ClearSlabFrozen(struct page *page) +{ + ClearPageActive(page); +} + static inline int SlabDebug(struct page *page) { #ifdef CONFIG_SLUB_DEBUG @@ -1135,11 +1158,12 @@ static void remove_partial(struct kmem_cache *s, * * Must hold list_lock. */ -static int lock_and_del_slab(struct kmem_cache_node *n, struct page *page) +static inline int lock_and_freeze_slab(struct kmem_cache_node *n, struct page *page) { if (slab_trylock(page)) { list_del(&page->lru); n->nr_partial--; + SetSlabFrozen(page); return 1; } return 0; @@ -1163,7 +1187,7 @@ static struct page *get_partial_node(struct kmem_cache_node *n) spin_lock(&n->list_lock); list_for_each_entry(page, &n->partial, lru) - if (lock_and_del_slab(n, page)) + if (lock_and_freeze_slab(n, page)) goto out; page = NULL; out: @@ -1242,10 +1266,11 @@ static struct page *get_partial(struct kmem_cache *s, gfp_t flags, int node) * * On exit the slab lock will have been dropped. */ -static void putback_slab(struct kmem_cache *s, struct page *page) +static void unfreeze_slab(struct kmem_cache *s, struct page *page) { struct kmem_cache_node *n = get_node(s, page_to_nid(page)); + ClearSlabFrozen(page); if (page->inuse) { if (page->freelist) @@ -1296,9 +1321,7 @@ static void deactivate_slab(struct kmem_cache *s, struct page *page, int cpu) page->inuse--; } s->cpu_slab[cpu] = NULL; - ClearPageActive(page); - - putback_slab(s, page); + unfreeze_slab(s, page); } static void flush_slab(struct kmem_cache *s, struct page *page, int cpu) @@ -1389,9 +1412,7 @@ static void *__slab_alloc(struct kmem_cache *s, new_slab: page = get_partial(s, gfpflags, node); if (page) { -have_slab: s->cpu_slab[cpu] = page; - SetPageActive(page); goto load_freelist; } @@ -1421,7 +1442,9 @@ static void *__slab_alloc(struct kmem_cache *s, flush_slab(s, s->cpu_slab[cpu], cpu); } slab_lock(page); - goto have_slab; + SetSlabFrozen(page); + s->cpu_slab[cpu] = page; + goto load_freelist; } return NULL; debug: @@ -1508,11 +1531,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page, page->freelist = object; page->inuse--; - if (unlikely(PageActive(page))) - /* - * Cpu slabs are never on partial lists and are - * never freed. - */ + if (unlikely(SlabFrozen(page))) goto out_unlock; if (unlikely(!page->inuse)) @@ -1544,7 +1563,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page, debug: if (!free_object_checks(s, page, x)) goto out_unlock; - if (!PageActive(page) && !page->freelist) + if (!SlabFrozen(page) && !page->freelist) remove_full(s, page); if (s->flags & SLAB_STORE_USER) set_track(s, x, TRACK_FREE, addr); From 0b44f7a5b5078d737b3f5914978aabb761254840 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 16 May 2007 22:10:53 -0700 Subject: [PATCH 06/34] slab: warn on zero-length allocations slub warns on this, and we're working on making kmalloc(0) return NULL. Let's make slab warn as well so our testers detect such callers more rapidly. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slab.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/slab.c b/mm/slab.c index 12344432e201f..2043102c0425e 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -789,6 +789,7 @@ static inline struct kmem_cache *__find_general_cachep(size_t size, */ BUG_ON(malloc_sizes[INDEX_AC].cs_cachep == NULL); #endif + WARN_ON_ONCE(size == 0); while (size > csizep->cs_size) csizep++; From ade3aff25fb2dce76e2a9b53e1334bd0a174f739 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 16 May 2007 22:10:54 -0700 Subject: [PATCH 07/34] slub: fix handling of oversized slabs I'm getting zillions of undefined references to __kmalloc_size_too_large on alpha. For some reason alpha is building out-of-line copies of kmalloc_slab() into lots of compilation units. It turns out that gcc just isn't smart enough to work out that __builtin_contant_p(size)==true implies that __builtin_contant_p(index)==true. So let's give it a bit of help. Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/slub_def.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index 5e2e7297dfaaa..a9fb92862aaa3 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -145,7 +145,12 @@ static inline struct kmem_cache *kmalloc_slab(size_t size) if (index == 0) return NULL; - if (index < 0) { + /* + * This function only gets expanded if __builtin_constant_p(size), so + * testing it here shouldn't be needed. But some versions of gcc need + * help. + */ + if (__builtin_constant_p(size) && index < 0) { /* * Generate a link failure. Would be great if we could * do something to stop the compile here. From eefaca9c3246f3daf56e7ed02987f79abcee7087 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 16 May 2007 22:10:55 -0700 Subject: [PATCH 08/34] SLUB: slabinfo fixes Align the output of % with K/M/G of sizes. Check for empty NUMA information to avoid segfault on !NUMA. -r should work directly not only if we match a single slab without additional options. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/vm/slabinfo.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Documentation/vm/slabinfo.c b/Documentation/vm/slabinfo.c index 686a8e04a4f3c..434af27a32ac1 100644 --- a/Documentation/vm/slabinfo.c +++ b/Documentation/vm/slabinfo.c @@ -242,6 +242,9 @@ void decode_numa_list(int *numa, char *t) memset(numa, 0, MAX_NODES * sizeof(int)); + if (!t) + return; + while (*t == 'N') { t++; node = strtoul(t, &t, 10); @@ -386,7 +389,9 @@ void report(struct slabinfo *s) { if (strcmp(s->name, "*") == 0) return; - printf("\nSlabcache: %-20s Aliases: %2d Order : %2d\n", s->name, s->aliases, s->order); + + printf("\nSlabcache: %-20s Aliases: %2d Order : %2d Objects: %d\n", + s->name, s->aliases, s->order, s->objects); if (s->hwcache_align) printf("** Hardware cacheline aligned\n"); if (s->cache_dma) @@ -791,11 +796,11 @@ void totals(void) store_size(b1, total_size);store_size(b2, total_waste); store_size(b3, total_waste * 100 / total_used); - printf("Memory used: %6s # Loss : %6s MRatio: %6s%%\n", b1, b2, b3); + printf("Memory used: %6s # Loss : %6s MRatio:%6s%%\n", b1, b2, b3); store_size(b1, total_objects);store_size(b2, total_partobj); store_size(b3, total_partobj * 100 / total_objects); - printf("# Objects : %6s # PartObj: %6s ORatio: %6s%%\n", b1, b2, b3); + printf("# Objects : %6s # PartObj: %6s ORatio:%6s%%\n", b1, b2, b3); printf("\n"); printf("Per Cache Average Min Max Total\n"); @@ -818,7 +823,7 @@ void totals(void) store_size(b1, avg_ppart);store_size(b2, min_ppart); store_size(b3, max_ppart); store_size(b4, total_partial * 100 / total_slabs); - printf("%%PartSlab %10s%% %10s%% %10s%% %10s%%\n", + printf("%%PartSlab%10s%% %10s%% %10s%% %10s%%\n", b1, b2, b3, b4); store_size(b1, avg_partobj);store_size(b2, min_partobj); @@ -830,7 +835,7 @@ void totals(void) store_size(b1, avg_ppartobj);store_size(b2, min_ppartobj); store_size(b3, max_ppartobj); store_size(b4, total_partobj * 100 / total_objects); - printf("%% PartObj %10s%% %10s%% %10s%% %10s%%\n", + printf("%% PartObj%10s%% %10s%% %10s%% %10s%%\n", b1, b2, b3, b4); store_size(b1, avg_size);store_size(b2, min_size); @@ -1100,6 +1105,8 @@ void output_slabs(void) ops(slab); else if (show_slab) slabcache(slab); + else if (show_report) + report(slab); } } From 5577bd8a85c8b7643a241789b14fafa9c8a6c7db Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 16 May 2007 22:10:56 -0700 Subject: [PATCH 09/34] SLUB: Do our own flags based on PG_active and PG_error The atomicity when handling flags in SLUB is not necessary since both flags used by SLUB are not updated in a racy way. Flag updates are either done during slab creation or destruction or under slab_lock. Some of these flags do not have the non atomic variants that we need. So define our own. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slub.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index ce96d485a88f9..3ca164f339651 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -99,42 +99,42 @@ * the fast path and disables lockless freelists. */ +#define FROZEN (1 << PG_active) + +#ifdef CONFIG_SLUB_DEBUG +#define SLABDEBUG (1 << PG_error) +#else +#define SLABDEBUG 0 +#endif + static inline int SlabFrozen(struct page *page) { - return PageActive(page); + return page->flags & FROZEN; } static inline void SetSlabFrozen(struct page *page) { - SetPageActive(page); + page->flags |= FROZEN; } static inline void ClearSlabFrozen(struct page *page) { - ClearPageActive(page); + page->flags &= ~FROZEN; } static inline int SlabDebug(struct page *page) { -#ifdef CONFIG_SLUB_DEBUG - return PageError(page); -#else - return 0; -#endif + return page->flags & SLABDEBUG; } static inline void SetSlabDebug(struct page *page) { -#ifdef CONFIG_SLUB_DEBUG - SetPageError(page); -#endif + page->flags |= SLABDEBUG; } static inline void ClearSlabDebug(struct page *page) { -#ifdef CONFIG_SLUB_DEBUG - ClearPageError(page); -#endif + page->flags &= ~SLABDEBUG; } /* From a35afb830f8d71ec211531aeb9a621b09a2efb39 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 16 May 2007 22:10:57 -0700 Subject: [PATCH 10/34] Remove SLAB_CTOR_CONSTRUCTOR SLAB_CTOR_CONSTRUCTOR is always specified. No point in checking it. Signed-off-by: Christoph Lameter Cc: David Howells Cc: Jens Axboe Cc: Steven French Cc: Michael Halcrow Cc: OGAWA Hirofumi Cc: Miklos Szeredi Cc: Steven Whitehouse Cc: Roman Zippel Cc: David Woodhouse Cc: Dave Kleikamp Cc: Trond Myklebust Cc: "J. Bruce Fields" Cc: Anton Altaparmakov Cc: Mark Fasheh Cc: Paul Mackerras Cc: Christoph Hellwig Cc: Jan Kara Cc: David Chinner Cc: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/platforms/cell/spufs/inode.c | 4 +-- drivers/mtd/ubi/eba.c | 3 -- fs/adfs/super.c | 3 +- fs/affs/super.c | 8 ++--- fs/afs/super.c | 20 ++++++------ fs/befs/linuxvfs.c | 6 ++-- fs/bfs/inode.c | 3 +- fs/block_dev.c | 16 +++++----- fs/buffer.c | 22 +++---------- fs/cifs/cifsfs.c | 6 ++-- fs/coda/inode.c | 3 +- fs/ecryptfs/main.c | 3 +- fs/efs/super.c | 3 +- fs/ext2/super.c | 8 ++--- fs/ext3/super.c | 10 +++--- fs/ext4/super.c | 10 +++--- fs/fat/cache.c | 3 +- fs/fat/inode.c | 14 ++++----- fs/fuse/inode.c | 3 +- fs/gfs2/main.c | 34 ++++++++++---------- fs/hfs/super.c | 3 +- fs/hfsplus/super.c | 3 +- fs/hpfs/super.c | 8 ++--- fs/hugetlbfs/inode.c | 3 +- fs/inode.c | 3 +- fs/isofs/inode.c | 3 +- fs/jffs2/super.c | 6 ++-- fs/jfs/jfs_metapage.c | 18 +++++------ fs/jfs/super.c | 22 ++++++------- fs/locks.c | 3 -- fs/minix/inode.c | 3 +- fs/ncpfs/inode.c | 6 ++-- fs/nfs/inode.c | 28 ++++++++--------- fs/ntfs/super.c | 3 +- fs/ocfs2/dlm/dlmfs.c | 8 ++--- fs/ocfs2/super.c | 38 +++++++++++------------ fs/openpromfs/inode.c | 3 +- fs/proc/inode.c | 3 +- fs/qnx4/inode.c | 3 +- fs/reiserfs/super.c | 10 +++--- fs/romfs/inode.c | 7 ++--- fs/smbfs/inode.c | 3 +- fs/sysv/inode.c | 3 +- fs/udf/super.c | 6 ++-- fs/ufs/super.c | 3 +- fs/xfs/linux-2.6/xfs_super.c | 3 +- include/linux/slab.h | 3 -- ipc/mqueue.c | 3 +- kernel/fork.c | 6 ++-- mm/rmap.c | 8 ++--- mm/shmem.c | 8 ++--- mm/slab.c | 12 +++---- mm/slob.c | 2 +- mm/slub.c | 2 +- net/socket.c | 3 +- net/sunrpc/rpc_pipe.c | 24 +++++++------- 56 files changed, 178 insertions(+), 277 deletions(-) diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index a93f328a73178..7150730e2ff11 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -71,9 +71,7 @@ spufs_init_once(void *p, struct kmem_cache * cachep, unsigned long flags) { struct spufs_inode_info *ei = p; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - inode_init_once(&ei->vfs_inode); - } + inode_init_once(&ei->vfs_inode); } static struct inode * diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 3dba5733ed1fe..74002945b71b6 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -940,9 +940,6 @@ static void ltree_entry_ctor(void *obj, struct kmem_cache *cache, { struct ltree_entry *le = obj; - if (flags & SLAB_CTOR_CONSTRUCTOR) - return; - le->users = 0; init_rwsem(&le->mutex); } diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 30c296508497d..de2ed5ca33519 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c @@ -232,8 +232,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct adfs_inode_info *ei = (struct adfs_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/affs/super.c b/fs/affs/super.c index beff7d21e6e2f..b800d451cd602 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -87,11 +87,9 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct affs_inode_info *ei = (struct affs_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - init_MUTEX(&ei->i_link_lock); - init_MUTEX(&ei->i_ext_lock); - inode_init_once(&ei->vfs_inode); - } + init_MUTEX(&ei->i_link_lock); + init_MUTEX(&ei->i_ext_lock); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/afs/super.c b/fs/afs/super.c index 370cecc910db4..8d47ad88a0932 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -451,17 +451,15 @@ static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep, { struct afs_vnode *vnode = _vnode; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - memset(vnode, 0, sizeof(*vnode)); - inode_init_once(&vnode->vfs_inode); - init_waitqueue_head(&vnode->update_waitq); - mutex_init(&vnode->permits_lock); - mutex_init(&vnode->validate_lock); - spin_lock_init(&vnode->writeback_lock); - spin_lock_init(&vnode->lock); - INIT_LIST_HEAD(&vnode->writebacks); - INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work); - } + memset(vnode, 0, sizeof(*vnode)); + inode_init_once(&vnode->vfs_inode); + init_waitqueue_head(&vnode->update_waitq); + mutex_init(&vnode->permits_lock); + mutex_init(&vnode->validate_lock); + spin_lock_init(&vnode->writeback_lock); + spin_lock_init(&vnode->lock); + INIT_LIST_HEAD(&vnode->writebacks); + INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work); } /* diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index fe96108a788d6..a5c5171c28289 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -292,10 +292,8 @@ befs_destroy_inode(struct inode *inode) static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct befs_inode_info *bi = (struct befs_inode_info *) foo; - - if (flags & SLAB_CTOR_CONSTRUCTOR) { - inode_init_once(&bi->vfs_inode); - } + + inode_init_once(&bi->vfs_inode); } static void diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index edc08d89aabc5..58c7bd9f53015 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -248,8 +248,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct bfs_inode_info *bi = foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&bi->vfs_inode); + inode_init_once(&bi->vfs_inode); } static int init_inodecache(void) diff --git a/fs/block_dev.c b/fs/block_dev.c index 742899240872f..ea1480a16f517 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -458,17 +458,15 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag struct bdev_inode *ei = (struct bdev_inode *) foo; struct block_device *bdev = &ei->bdev; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - memset(bdev, 0, sizeof(*bdev)); - mutex_init(&bdev->bd_mutex); - sema_init(&bdev->bd_mount_sem, 1); - INIT_LIST_HEAD(&bdev->bd_inodes); - INIT_LIST_HEAD(&bdev->bd_list); + memset(bdev, 0, sizeof(*bdev)); + mutex_init(&bdev->bd_mutex); + sema_init(&bdev->bd_mount_sem, 1); + INIT_LIST_HEAD(&bdev->bd_inodes); + INIT_LIST_HEAD(&bdev->bd_list); #ifdef CONFIG_SYSFS - INIT_LIST_HEAD(&bdev->bd_holder_list); + INIT_LIST_HEAD(&bdev->bd_holder_list); #endif - inode_init_once(&ei->vfs_inode); - } + inode_init_once(&ei->vfs_inode); } static inline void __bd_forget(struct inode *inode) diff --git a/fs/buffer.c b/fs/buffer.c index aecd057cd0e06..3deeb886f6e6f 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2898,8 +2898,9 @@ static void recalc_bh_state(void) struct buffer_head *alloc_buffer_head(gfp_t gfp_flags) { - struct buffer_head *ret = kmem_cache_alloc(bh_cachep, gfp_flags); + struct buffer_head *ret = kmem_cache_zalloc(bh_cachep, gfp_flags); if (ret) { + INIT_LIST_HEAD(&ret->b_assoc_buffers); get_cpu_var(bh_accounting).nr++; recalc_bh_state(); put_cpu_var(bh_accounting); @@ -2918,17 +2919,6 @@ void free_buffer_head(struct buffer_head *bh) } EXPORT_SYMBOL(free_buffer_head); -static void -init_buffer_head(void *data, struct kmem_cache *cachep, unsigned long flags) -{ - if (flags & SLAB_CTOR_CONSTRUCTOR) { - struct buffer_head * bh = (struct buffer_head *)data; - - memset(bh, 0, sizeof(*bh)); - INIT_LIST_HEAD(&bh->b_assoc_buffers); - } -} - static void buffer_exit_cpu(int cpu) { int i; @@ -2955,12 +2945,8 @@ void __init buffer_init(void) { int nrpages; - bh_cachep = kmem_cache_create("buffer_head", - sizeof(struct buffer_head), 0, - (SLAB_RECLAIM_ACCOUNT|SLAB_PANIC| - SLAB_MEM_SPREAD), - init_buffer_head, - NULL); + bh_cachep = KMEM_CACHE(buffer_head, + SLAB_RECLAIM_ACCOUNT|SLAB_PANIC|SLAB_MEM_SPREAD); /* * Limit the bh occupancy to 10% of ZONE_NORMAL diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 8568e100953cd..d38c69b591cfe 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -701,10 +701,8 @@ cifs_init_once(void *inode, struct kmem_cache * cachep, unsigned long flags) { struct cifsInodeInfo *cifsi = inode; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - inode_init_once(&cifsi->vfs_inode); - INIT_LIST_HEAD(&cifsi->lockList); - } + inode_init_once(&cifsi->vfs_inode); + INIT_LIST_HEAD(&cifsi->lockList); } static int diff --git a/fs/coda/inode.c b/fs/coda/inode.c index 0aaff3651d146..dbff1bd4fb96b 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c @@ -62,8 +62,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct coda_inode_info *ei = (struct coda_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } int coda_init_inodecache(void) diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 8cbf3f69ebe5a..606128f5c927d 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c @@ -583,8 +583,7 @@ inode_info_init_once(void *vptr, struct kmem_cache *cachep, unsigned long flags) { struct ecryptfs_inode_info *ei = (struct ecryptfs_inode_info *)vptr; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static struct ecryptfs_cache_info { diff --git a/fs/efs/super.c b/fs/efs/super.c index ba7a8b9da0c16..e0a6839e68ae0 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -72,8 +72,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct efs_inode_info *ei = (struct efs_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 685a1c287177f..16337bff0272e 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -160,13 +160,11 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct ext2_inode_info *ei = (struct ext2_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - rwlock_init(&ei->i_meta_lock); + rwlock_init(&ei->i_meta_lock); #ifdef CONFIG_EXT2_FS_XATTR - init_rwsem(&ei->xattr_sem); + init_rwsem(&ei->xattr_sem); #endif - inode_init_once(&ei->vfs_inode); - } + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 54d3c90412598..6e3062913a92f 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -466,14 +466,12 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct ext3_inode_info *ei = (struct ext3_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - INIT_LIST_HEAD(&ei->i_orphan); + INIT_LIST_HEAD(&ei->i_orphan); #ifdef CONFIG_EXT3_FS_XATTR - init_rwsem(&ei->xattr_sem); + init_rwsem(&ei->xattr_sem); #endif - mutex_init(&ei->truncate_mutex); - inode_init_once(&ei->vfs_inode); - } + mutex_init(&ei->truncate_mutex); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 7191269323548..cb9afdd0e26e5 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -517,14 +517,12 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct ext4_inode_info *ei = (struct ext4_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - INIT_LIST_HEAD(&ei->i_orphan); + INIT_LIST_HEAD(&ei->i_orphan); #ifdef CONFIG_EXT4DEV_FS_XATTR - init_rwsem(&ei->xattr_sem); + init_rwsem(&ei->xattr_sem); #endif - mutex_init(&ei->truncate_mutex); - inode_init_once(&ei->vfs_inode); - } + mutex_init(&ei->truncate_mutex); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/fat/cache.c b/fs/fat/cache.c index 1959143c1d27a..3c9c8a15ec73f 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -40,8 +40,7 @@ static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct fat_cache *cache = (struct fat_cache *)foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - INIT_LIST_HEAD(&cache->cache_list); + INIT_LIST_HEAD(&cache->cache_list); } int __init fat_cache_init(void) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 2c55e8dce7932..479722d896673 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -500,14 +500,12 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct msdos_inode_info *ei = (struct msdos_inode_info *)foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - spin_lock_init(&ei->cache_lru_lock); - ei->nr_caches = 0; - ei->cache_valid_id = FAT_CACHE_VALID + 1; - INIT_LIST_HEAD(&ei->cache_lru); - INIT_HLIST_NODE(&ei->i_fat_hash); - inode_init_once(&ei->vfs_inode); - } + spin_lock_init(&ei->cache_lru_lock); + ei->nr_caches = 0; + ei->cache_valid_id = FAT_CACHE_VALID + 1; + INIT_LIST_HEAD(&ei->cache_lru); + INIT_HLIST_NODE(&ei->i_fat_hash); + inode_init_once(&ei->vfs_inode); } static int __init fat_init_inodecache(void) diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 1397018ff4766..c3a2ad0da43c5 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -687,8 +687,7 @@ static void fuse_inode_init_once(void *foo, struct kmem_cache *cachep, { struct inode * inode = foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(inode); + inode_init_once(inode); } static int __init fuse_fs_init(void) diff --git a/fs/gfs2/main.c b/fs/gfs2/main.c index e460487c05574..787a0edef1005 100644 --- a/fs/gfs2/main.c +++ b/fs/gfs2/main.c @@ -27,29 +27,27 @@ static void gfs2_init_inode_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct gfs2_inode *ip = foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - inode_init_once(&ip->i_inode); - spin_lock_init(&ip->i_spin); - init_rwsem(&ip->i_rw_mutex); - memset(ip->i_cache, 0, sizeof(ip->i_cache)); - } + + inode_init_once(&ip->i_inode); + spin_lock_init(&ip->i_spin); + init_rwsem(&ip->i_rw_mutex); + memset(ip->i_cache, 0, sizeof(ip->i_cache)); } static void gfs2_init_glock_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct gfs2_glock *gl = foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - INIT_HLIST_NODE(&gl->gl_list); - spin_lock_init(&gl->gl_spin); - INIT_LIST_HEAD(&gl->gl_holders); - INIT_LIST_HEAD(&gl->gl_waiters1); - INIT_LIST_HEAD(&gl->gl_waiters3); - gl->gl_lvb = NULL; - atomic_set(&gl->gl_lvb_count, 0); - INIT_LIST_HEAD(&gl->gl_reclaim); - INIT_LIST_HEAD(&gl->gl_ail_list); - atomic_set(&gl->gl_ail_count, 0); - } + + INIT_HLIST_NODE(&gl->gl_list); + spin_lock_init(&gl->gl_spin); + INIT_LIST_HEAD(&gl->gl_holders); + INIT_LIST_HEAD(&gl->gl_waiters1); + INIT_LIST_HEAD(&gl->gl_waiters3); + gl->gl_lvb = NULL; + atomic_set(&gl->gl_lvb_count, 0); + INIT_LIST_HEAD(&gl->gl_reclaim); + INIT_LIST_HEAD(&gl->gl_ail_list); + atomic_set(&gl->gl_ail_count, 0); } /** diff --git a/fs/hfs/super.c b/fs/hfs/super.c index 4f1888f16cf0b..92cf8751e4287 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -434,8 +434,7 @@ static void hfs_init_once(void *p, struct kmem_cache *cachep, unsigned long flag { struct hfs_inode_info *i = p; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&i->vfs_inode); + inode_init_once(&i->vfs_inode); } static int __init init_hfs_fs(void) diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 37afbec8a7612..ebd1b380cbbc9 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -470,8 +470,7 @@ static void hfsplus_init_once(void *p, struct kmem_cache *cachep, unsigned long { struct hfsplus_inode_info *i = p; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&i->vfs_inode); + inode_init_once(&i->vfs_inode); } static int __init init_hfsplus_fs(void) diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 1b95f39fbc37a..fca1165d71921 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -176,11 +176,9 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct hpfs_inode_info *ei = (struct hpfs_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - mutex_init(&ei->i_mutex); - mutex_init(&ei->i_parent_mutex); - inode_init_once(&ei->vfs_inode); - } + mutex_init(&ei->i_mutex); + mutex_init(&ei->i_parent_mutex); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 98959b87cdf8f..aa083dd34e924 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -556,8 +556,7 @@ static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct hugetlbfs_inode_info *ei = (struct hugetlbfs_inode_info *)foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } const struct file_operations hugetlbfs_file_operations = { diff --git a/fs/inode.c b/fs/inode.c index df2ef15d03d25..9a012cc5b6cd6 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -213,8 +213,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct inode * inode = (struct inode *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(inode); + inode_init_once(inode); } /* diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index e99f7ff4ecb44..5c3eecf7542ee 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -77,8 +77,7 @@ static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags { struct iso_inode_info *ei = foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 45368f8bbe72d..6488af43bc9b7 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -47,10 +47,8 @@ static void jffs2_i_init_once(void * foo, struct kmem_cache * cachep, unsigned l { struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - init_MUTEX(&ei->sem); - inode_init_once(&ei->vfs_inode); - } + init_MUTEX(&ei->sem); + inode_init_once(&ei->vfs_inode); } static int jffs2_sync_fs(struct super_block *sb, int wait) diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 6b3acb0b57811..43d4f69afbeca 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -184,16 +184,14 @@ static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct metapage *mp = (struct metapage *)foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - mp->lid = 0; - mp->lsn = 0; - mp->flag = 0; - mp->data = NULL; - mp->clsn = 0; - mp->log = NULL; - set_bit(META_free, &mp->flag); - init_waitqueue_head(&mp->wait); - } + mp->lid = 0; + mp->lsn = 0; + mp->flag = 0; + mp->data = NULL; + mp->clsn = 0; + mp->log = NULL; + set_bit(META_free, &mp->flag); + init_waitqueue_head(&mp->wait); } static inline struct metapage *alloc_metapage(gfp_t gfp_mask) diff --git a/fs/jfs/super.c b/fs/jfs/super.c index ea9dc3e65dcf7..20e4ac1c79a3c 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c @@ -752,20 +752,18 @@ static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags { struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - memset(jfs_ip, 0, sizeof(struct jfs_inode_info)); - INIT_LIST_HEAD(&jfs_ip->anon_inode_list); - init_rwsem(&jfs_ip->rdwrlock); - mutex_init(&jfs_ip->commit_mutex); - init_rwsem(&jfs_ip->xattr_sem); - spin_lock_init(&jfs_ip->ag_lock); - jfs_ip->active_ag = -1; + memset(jfs_ip, 0, sizeof(struct jfs_inode_info)); + INIT_LIST_HEAD(&jfs_ip->anon_inode_list); + init_rwsem(&jfs_ip->rdwrlock); + mutex_init(&jfs_ip->commit_mutex); + init_rwsem(&jfs_ip->xattr_sem); + spin_lock_init(&jfs_ip->ag_lock); + jfs_ip->active_ag = -1; #ifdef CONFIG_JFS_POSIX_ACL - jfs_ip->i_acl = JFS_ACL_NOT_CACHED; - jfs_ip->i_default_acl = JFS_ACL_NOT_CACHED; + jfs_ip->i_acl = JFS_ACL_NOT_CACHED; + jfs_ip->i_default_acl = JFS_ACL_NOT_CACHED; #endif - inode_init_once(&jfs_ip->vfs_inode); - } + inode_init_once(&jfs_ip->vfs_inode); } static int __init init_jfs_fs(void) diff --git a/fs/locks.c b/fs/locks.c index 8ec16ab5ef744..431a8b871fcef 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -203,9 +203,6 @@ static void init_once(void *foo, struct kmem_cache *cache, unsigned long flags) { struct file_lock *lock = (struct file_lock *) foo; - if (!(flags & SLAB_CTOR_CONSTRUCTOR)) - return; - locks_init_lock(lock); } diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 2f4d43a2a3105..be4044614ac83 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -73,8 +73,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct minix_inode_info *ei = (struct minix_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index c29f00ad495d9..cf06eb9f050e3 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -60,10 +60,8 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct ncp_inode_info *ei = (struct ncp_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - mutex_init(&ei->open_mutex); - inode_init_once(&ei->vfs_inode); - } + mutex_init(&ei->open_mutex); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 2a3fd9573207a..2b26ad7c97708 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1164,21 +1164,19 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct nfs_inode *nfsi = (struct nfs_inode *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - inode_init_once(&nfsi->vfs_inode); - spin_lock_init(&nfsi->req_lock); - INIT_LIST_HEAD(&nfsi->dirty); - INIT_LIST_HEAD(&nfsi->commit); - INIT_LIST_HEAD(&nfsi->open_files); - INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); - INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); - INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); - atomic_set(&nfsi->data_updates, 0); - nfsi->ndirty = 0; - nfsi->ncommit = 0; - nfsi->npages = 0; - nfs4_init_once(nfsi); - } + inode_init_once(&nfsi->vfs_inode); + spin_lock_init(&nfsi->req_lock); + INIT_LIST_HEAD(&nfsi->dirty); + INIT_LIST_HEAD(&nfsi->commit); + INIT_LIST_HEAD(&nfsi->open_files); + INIT_LIST_HEAD(&nfsi->access_cache_entry_lru); + INIT_LIST_HEAD(&nfsi->access_cache_inode_lru); + INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); + atomic_set(&nfsi->data_updates, 0); + nfsi->ndirty = 0; + nfsi->ncommit = 0; + nfsi->npages = 0; + nfs4_init_once(nfsi); } static int __init nfs_init_inodecache(void) diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 21d834e5ed733..4566b9182551c 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -3085,8 +3085,7 @@ static void ntfs_big_inode_init_once(void *foo, struct kmem_cache *cachep, { ntfs_inode *ni = (ntfs_inode *)foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(VFS_I(ni)); + inode_init_once(VFS_I(ni)); } /* diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c index 5671cf9d63835..fd8cb1badc9b9 100644 --- a/fs/ocfs2/dlm/dlmfs.c +++ b/fs/ocfs2/dlm/dlmfs.c @@ -262,12 +262,10 @@ static void dlmfs_init_once(void *foo, struct dlmfs_inode_private *ip = (struct dlmfs_inode_private *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - ip->ip_dlm = NULL; - ip->ip_parent = NULL; + ip->ip_dlm = NULL; + ip->ip_parent = NULL; - inode_init_once(&ip->ip_vfs_inode); - } + inode_init_once(&ip->ip_vfs_inode); } static struct inode *dlmfs_alloc_inode(struct super_block *sb) diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 7c5e3f5d66345..86b559c7dce9a 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -937,31 +937,29 @@ static void ocfs2_inode_init_once(void *data, { struct ocfs2_inode_info *oi = data; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - oi->ip_flags = 0; - oi->ip_open_count = 0; - spin_lock_init(&oi->ip_lock); - ocfs2_extent_map_init(&oi->vfs_inode); - INIT_LIST_HEAD(&oi->ip_io_markers); - oi->ip_created_trans = 0; - oi->ip_last_trans = 0; - oi->ip_dir_start_lookup = 0; + oi->ip_flags = 0; + oi->ip_open_count = 0; + spin_lock_init(&oi->ip_lock); + ocfs2_extent_map_init(&oi->vfs_inode); + INIT_LIST_HEAD(&oi->ip_io_markers); + oi->ip_created_trans = 0; + oi->ip_last_trans = 0; + oi->ip_dir_start_lookup = 0; - init_rwsem(&oi->ip_alloc_sem); - mutex_init(&oi->ip_io_mutex); + init_rwsem(&oi->ip_alloc_sem); + mutex_init(&oi->ip_io_mutex); - oi->ip_blkno = 0ULL; - oi->ip_clusters = 0; + oi->ip_blkno = 0ULL; + oi->ip_clusters = 0; - ocfs2_lock_res_init_once(&oi->ip_rw_lockres); - ocfs2_lock_res_init_once(&oi->ip_meta_lockres); - ocfs2_lock_res_init_once(&oi->ip_data_lockres); - ocfs2_lock_res_init_once(&oi->ip_open_lockres); + ocfs2_lock_res_init_once(&oi->ip_rw_lockres); + ocfs2_lock_res_init_once(&oi->ip_meta_lockres); + ocfs2_lock_res_init_once(&oi->ip_data_lockres); + ocfs2_lock_res_init_once(&oi->ip_open_lockres); - ocfs2_metadata_cache_init(&oi->vfs_inode); + ocfs2_metadata_cache_init(&oi->vfs_inode); - inode_init_once(&oi->vfs_inode); - } + inode_init_once(&oi->vfs_inode); } static int ocfs2_initialize_mem_caches(void) diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 731a90e9f0cd1..e62397341c363 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c @@ -419,8 +419,7 @@ static void op_inode_init_once(void *data, struct kmem_cache * cachep, unsigned { struct op_inode_info *oi = (struct op_inode_info *) data; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&oi->vfs_inode); + inode_init_once(&oi->vfs_inode); } static int __init init_openprom_fs(void) diff --git a/fs/proc/inode.c b/fs/proc/inode.c index b8171907c83b6..d5ce65c68d7b2 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -109,8 +109,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct proc_inode *ei = (struct proc_inode *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } int __init proc_init_inodecache(void) diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 75fc8498f2e29..8d256eb118130 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -536,8 +536,7 @@ static void init_once(void *foo, struct kmem_cache * cachep, { struct qnx4_inode_info *ei = (struct qnx4_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index c7762140c4258..b4ac9119200e6 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -511,14 +511,12 @@ static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags { struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *)foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - INIT_LIST_HEAD(&ei->i_prealloc_list); - inode_init_once(&ei->vfs_inode); + INIT_LIST_HEAD(&ei->i_prealloc_list); + inode_init_once(&ei->vfs_inode); #ifdef CONFIG_REISERFS_FS_POSIX_ACL - ei->i_acl_access = NULL; - ei->i_acl_default = NULL; + ei->i_acl_access = NULL; + ei->i_acl_default = NULL; #endif - } } static int init_inodecache(void) diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 8042851902718..2284e03342c6a 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c @@ -566,12 +566,11 @@ static void romfs_destroy_inode(struct inode *inode) kmem_cache_free(romfs_inode_cachep, ROMFS_I(inode)); } -static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) +static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { - struct romfs_inode_info *ei = (struct romfs_inode_info *) foo; + struct romfs_inode_info *ei = foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index 424a3ddf86dd3..5c9243a23b9bd 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c @@ -70,8 +70,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct smb_inode_info *ei = (struct smb_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 3152d74156067..5644116933945 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -322,8 +322,7 @@ static void init_once(void *p, struct kmem_cache *cachep, unsigned long flags) { struct sysv_inode_info *si = (struct sysv_inode_info *)p; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&si->vfs_inode); + inode_init_once(&si->vfs_inode); } const struct super_operations sysv_sops = { diff --git a/fs/udf/super.c b/fs/udf/super.c index 9b8644a06e53b..3a743d854c17b 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -134,10 +134,8 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct udf_inode_info *ei = (struct udf_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - ei->i_ext.i_data = NULL; - inode_init_once(&ei->vfs_inode); - } + ei->i_ext.i_data = NULL; + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/ufs/super.c b/fs/ufs/super.c index be7c48c5f203f..22ff6ed55ce9a 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -1237,8 +1237,7 @@ static void init_once(void * foo, struct kmem_cache * cachep, unsigned long flag { struct ufs_inode_info *ei = (struct ufs_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 14e2cbe5a8d54..bf9a9d5909be0 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c @@ -360,8 +360,7 @@ xfs_fs_inode_init_once( kmem_zone_t *zonep, unsigned long flags) { - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(vn_to_inode((bhv_vnode_t *)vnode)); + inode_init_once(vn_to_inode((bhv_vnode_t *)vnode)); } STATIC int diff --git a/include/linux/slab.h b/include/linux/slab.h index 5dbc0bae26e36..6fb2ae214152b 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -32,9 +32,6 @@ typedef struct kmem_cache kmem_cache_t __deprecated; #define SLAB_MEM_SPREAD 0x00100000UL /* Spread some memory over cpuset */ #define SLAB_TRACE 0x00200000UL /* Trace allocations and frees */ -/* Flags passed to a constructor functions */ -#define SLAB_CTOR_CONSTRUCTOR 0x001UL /* If not set, then deconstructor */ - /* * struct kmem_cache related prototypes */ diff --git a/ipc/mqueue.c b/ipc/mqueue.c index fab5707cb5f72..a242c83d89d60 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -215,8 +215,7 @@ static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags { struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&p->vfs_inode); + inode_init_once(&p->vfs_inode); } static struct inode *mqueue_alloc_inode(struct super_block *sb) diff --git a/kernel/fork.c b/kernel/fork.c index 49530e40ea8b7..87069cfc18a12 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1427,10 +1427,8 @@ static void sighand_ctor(void *data, struct kmem_cache *cachep, { struct sighand_struct *sighand = data; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - spin_lock_init(&sighand->siglock); - INIT_LIST_HEAD(&sighand->signalfd_list); - } + spin_lock_init(&sighand->siglock); + INIT_LIST_HEAD(&sighand->signalfd_list); } void __init proc_caches_init(void) diff --git a/mm/rmap.c b/mm/rmap.c index 304f51985c785..1c1af92732d50 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -162,12 +162,10 @@ void anon_vma_unlink(struct vm_area_struct *vma) static void anon_vma_ctor(void *data, struct kmem_cache *cachep, unsigned long flags) { - if (flags & SLAB_CTOR_CONSTRUCTOR) { - struct anon_vma *anon_vma = data; + struct anon_vma *anon_vma = data; - spin_lock_init(&anon_vma->lock); - INIT_LIST_HEAD(&anon_vma->head); - } + spin_lock_init(&anon_vma->lock); + INIT_LIST_HEAD(&anon_vma->head); } void __init anon_vma_init(void) diff --git a/mm/shmem.c b/mm/shmem.c index f01e8deed645b..e537317bec4d5 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2358,13 +2358,11 @@ static void init_once(void *foo, struct kmem_cache *cachep, { struct shmem_inode_info *p = (struct shmem_inode_info *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - inode_init_once(&p->vfs_inode); + inode_init_once(&p->vfs_inode); #ifdef CONFIG_TMPFS_POSIX_ACL - p->i_acl = NULL; - p->i_default_acl = NULL; + p->i_acl = NULL; + p->i_default_acl = NULL; #endif - } } static int init_inodecache(void) diff --git a/mm/slab.c b/mm/slab.c index 2043102c0425e..1dc0ce1d0d5dd 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2610,7 +2610,7 @@ static inline kmem_bufctl_t *slab_bufctl(struct slab *slabp) } static void cache_init_objs(struct kmem_cache *cachep, - struct slab *slabp, unsigned long ctor_flags) + struct slab *slabp) { int i; @@ -2634,7 +2634,7 @@ static void cache_init_objs(struct kmem_cache *cachep, */ if (cachep->ctor && !(cachep->flags & SLAB_POISON)) cachep->ctor(objp + obj_offset(cachep), cachep, - ctor_flags); + 0); if (cachep->flags & SLAB_RED_ZONE) { if (*dbg_redzone2(cachep, objp) != RED_INACTIVE) @@ -2650,7 +2650,7 @@ static void cache_init_objs(struct kmem_cache *cachep, cachep->buffer_size / PAGE_SIZE, 0); #else if (cachep->ctor) - cachep->ctor(objp, cachep, ctor_flags); + cachep->ctor(objp, cachep, 0); #endif slab_bufctl(slabp)[i] = i + 1; } @@ -2739,7 +2739,6 @@ static int cache_grow(struct kmem_cache *cachep, struct slab *slabp; size_t offset; gfp_t local_flags; - unsigned long ctor_flags; struct kmem_list3 *l3; /* @@ -2748,7 +2747,6 @@ static int cache_grow(struct kmem_cache *cachep, */ BUG_ON(flags & ~(GFP_DMA | GFP_LEVEL_MASK)); - ctor_flags = SLAB_CTOR_CONSTRUCTOR; local_flags = (flags & GFP_LEVEL_MASK); /* Take the l3 list lock to change the colour_next on this node */ check_irq_off(); @@ -2793,7 +2791,7 @@ static int cache_grow(struct kmem_cache *cachep, slabp->nodeid = nodeid; slab_map_pages(cachep, slabp, objp); - cache_init_objs(cachep, slabp, ctor_flags); + cache_init_objs(cachep, slabp); if (local_flags & __GFP_WAIT) local_irq_disable(); @@ -3077,7 +3075,7 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, #endif objp += obj_offset(cachep); if (cachep->ctor && cachep->flags & SLAB_POISON) - cachep->ctor(objp, cachep, SLAB_CTOR_CONSTRUCTOR); + cachep->ctor(objp, cachep, 0); #if ARCH_SLAB_MINALIGN if ((u32)objp & (ARCH_SLAB_MINALIGN-1)) { printk(KERN_ERR "0x%p: not aligned to ARCH_SLAB_MINALIGN=%d\n", diff --git a/mm/slob.c b/mm/slob.c index 79164a4f54ad2..71976c5d40d30 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -327,7 +327,7 @@ void *kmem_cache_alloc(struct kmem_cache *c, gfp_t flags) b = (void *)__get_free_pages(flags, get_order(c->size)); if (c->ctor) - c->ctor(b, c, SLAB_CTOR_CONSTRUCTOR); + c->ctor(b, c, 0); return b; } diff --git a/mm/slub.c b/mm/slub.c index 3ca164f339651..e7ad123bb6a74 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -994,7 +994,7 @@ static void setup_object(struct kmem_cache *s, struct page *page, } if (unlikely(s->ctor)) - s->ctor(object, s, SLAB_CTOR_CONSTRUCTOR); + s->ctor(object, s, 0); } static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node) diff --git a/net/socket.c b/net/socket.c index 98a8f67abbfcf..f4530196a70a3 100644 --- a/net/socket.c +++ b/net/socket.c @@ -261,8 +261,7 @@ static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) { struct socket_alloc *ei = (struct socket_alloc *)foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) - inode_init_once(&ei->vfs_inode); + inode_init_once(&ei->vfs_inode); } static int init_inodecache(void) diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index a2f1893bde53e..5887457dc936d 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -828,19 +828,17 @@ init_once(void * foo, struct kmem_cache * cachep, unsigned long flags) { struct rpc_inode *rpci = (struct rpc_inode *) foo; - if (flags & SLAB_CTOR_CONSTRUCTOR) { - inode_init_once(&rpci->vfs_inode); - rpci->private = NULL; - rpci->nreaders = 0; - rpci->nwriters = 0; - INIT_LIST_HEAD(&rpci->in_upcall); - INIT_LIST_HEAD(&rpci->pipe); - rpci->pipelen = 0; - init_waitqueue_head(&rpci->waitq); - INIT_DELAYED_WORK(&rpci->queue_timeout, - rpc_timeout_upcall_queue); - rpci->ops = NULL; - } + inode_init_once(&rpci->vfs_inode); + rpci->private = NULL; + rpci->nreaders = 0; + rpci->nwriters = 0; + INIT_LIST_HEAD(&rpci->in_upcall); + INIT_LIST_HEAD(&rpci->pipe); + rpci->pipelen = 0; + init_waitqueue_head(&rpci->waitq); + INIT_DELAYED_WORK(&rpci->queue_timeout, + rpc_timeout_upcall_queue); + rpci->ops = NULL; } int register_rpc_pipefs(void) From 3ec0974210fe1b7c0618ad6e39a882a4237d7de2 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 16 May 2007 22:11:00 -0700 Subject: [PATCH 11/34] SLUB: Simplify debug code Consolidate functionality into the #ifdef section. Extract tracing into one subroutine. Move object debug processing into the #ifdef section so that the code in __slab_alloc and __slab_free becomes minimal. Reduce number of functions we need to provide stubs for in the !SLUB_DEBUG case. Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/slub.c | 112 +++++++++++++++++++++++++++--------------------------- 1 file changed, 57 insertions(+), 55 deletions(-) diff --git a/mm/slub.c b/mm/slub.c index e7ad123bb6a74..98801d404d699 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -742,6 +742,22 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search) return search == NULL; } +static void trace(struct kmem_cache *s, struct page *page, void *object, int alloc) +{ + if (s->flags & SLAB_TRACE) { + printk(KERN_INFO "TRACE %s %s 0x%p inuse=%d fp=0x%p\n", + s->name, + alloc ? "alloc" : "free", + object, page->inuse, + page->freelist); + + if (!alloc) + print_section("Object", (void *)object, s->objsize); + + dump_stack(); + } +} + /* * Tracking of fully allocated slabs for debugging purposes. */ @@ -766,8 +782,18 @@ static void remove_full(struct kmem_cache *s, struct page *page) spin_unlock(&n->list_lock); } -static int alloc_object_checks(struct kmem_cache *s, struct page *page, - void *object) +static void setup_object_debug(struct kmem_cache *s, struct page *page, + void *object) +{ + if (!(s->flags & (SLAB_STORE_USER|SLAB_RED_ZONE|__OBJECT_POISON))) + return; + + init_object(s, object, 0); + init_tracking(s, object); +} + +static int alloc_debug_processing(struct kmem_cache *s, struct page *page, + void *object, void *addr) { if (!check_slab(s, page)) goto bad; @@ -782,13 +808,16 @@ static int alloc_object_checks(struct kmem_cache *s, struct page *page, goto bad; } - if (!object) - return 1; - - if (!check_object(s, page, object, 0)) + if (object && !check_object(s, page, object, 0)) goto bad; + /* Success perform special debug activities for allocs */ + if (s->flags & SLAB_STORE_USER) + set_track(s, object, TRACK_ALLOC, addr); + trace(s, page, object, 1); + init_object(s, object, 1); return 1; + bad: if (PageSlab(page)) { /* @@ -806,8 +835,8 @@ static int alloc_object_checks(struct kmem_cache *s, struct page *page, return 0; } -static int free_object_checks(struct kmem_cache *s, struct page *page, - void *object) +static int free_debug_processing(struct kmem_cache *s, struct page *page, + void *object, void *addr) { if (!check_slab(s, page)) goto fail; @@ -841,29 +870,22 @@ static int free_object_checks(struct kmem_cache *s, struct page *page, "to slab %s", object, page->slab->name); goto fail; } + + /* Special debug activities for freeing objects */ + if (!SlabFrozen(page) && !page->freelist) + remove_full(s, page); + if (s->flags & SLAB_STORE_USER) + set_track(s, object, TRACK_FREE, addr); + trace(s, page, object, 0); + init_object(s, object, 0); return 1; + fail: printk(KERN_ERR "@@@ SLUB: %s slab 0x%p object at 0x%p not freed.\n", s->name, page, object); return 0; } -static void trace(struct kmem_cache *s, struct page *page, void *object, int alloc) -{ - if (s->flags & SLAB_TRACE) { - printk(KERN_INFO "TRACE %s %s 0x%p inuse=%d fp=0x%p\n", - s->name, - alloc ? "alloc" : "free", - object, page->inuse, - page->freelist); - - if (!alloc) - print_section("Object", (void *)object, s->objsize); - - dump_stack(); - } -} - static int __init setup_slub_debug(char *str) { if (!str || *str != '=') @@ -932,26 +954,20 @@ static void kmem_cache_open_debug_check(struct kmem_cache *s) s->flags |= slub_debug; } #else +static inline void setup_object_debug(struct kmem_cache *s, + struct page *page, void *object) {} -static inline int alloc_object_checks(struct kmem_cache *s, - struct page *page, void *object) { return 0; } +static inline int alloc_debug_processing(struct kmem_cache *s, + struct page *page, void *object, void *addr) { return 0; } -static inline int free_object_checks(struct kmem_cache *s, - struct page *page, void *object) { return 0; } +static inline int free_debug_processing(struct kmem_cache *s, + struct page *page, void *object, void *addr) { return 0; } -static inline void add_full(struct kmem_cache_node *n, struct page *page) {} -static inline void remove_full(struct kmem_cache *s, struct page *page) {} -static inline void trace(struct kmem_cache *s, struct page *page, - void *object, int alloc) {} -static inline void init_object(struct kmem_cache *s, - void *object, int active) {} -static inline void init_tracking(struct kmem_cache *s, void *object) {} static inline int slab_pad_check(struct kmem_cache *s, struct page *page) { return 1; } static inline int check_object(struct kmem_cache *s, struct page *page, void *object, int active) { return 1; } -static inline void set_track(struct kmem_cache *s, void *object, - enum track_item alloc, void *addr) {} +static inline void add_full(struct kmem_cache_node *n, struct page *page) {} static inline void kmem_cache_open_debug_check(struct kmem_cache *s) {} #define slub_debug 0 #endif @@ -988,11 +1004,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) static void setup_object(struct kmem_cache *s, struct page *page, void *object) { - if (SlabDebug(page)) { - init_object(s, object, 0); - init_tracking(s, object); - } - + setup_object_debug(s, page, object); if (unlikely(s->ctor)) s->ctor(object, s, 0); } @@ -1449,12 +1461,8 @@ static void *__slab_alloc(struct kmem_cache *s, return NULL; debug: object = page->freelist; - if (!alloc_object_checks(s, page, object)) + if (!alloc_debug_processing(s, page, object, addr)) goto another_slab; - if (s->flags & SLAB_STORE_USER) - set_track(s, object, TRACK_ALLOC, addr); - trace(s, page, object, 1); - init_object(s, object, 1); page->inuse++; page->freelist = object[page->offset]; @@ -1561,14 +1569,8 @@ static void __slab_free(struct kmem_cache *s, struct page *page, return; debug: - if (!free_object_checks(s, page, x)) + if (!free_debug_processing(s, page, x, addr)) goto out_unlock; - if (!SlabFrozen(page) && !page->freelist) - remove_full(s, page); - if (s->flags & SLAB_STORE_USER) - set_track(s, x, TRACK_FREE, addr); - trace(s, page, object, 0); - init_object(s, object, 0); goto checks_ok; } @@ -1805,7 +1807,7 @@ static struct kmem_cache_node * __init early_kmem_cache_node_alloc(gfp_t gfpflag page->freelist = get_freepointer(kmalloc_caches, n); page->inuse++; kmalloc_caches->node[node] = n; - init_object(kmalloc_caches, n, 1); + setup_object_debug(kmalloc_caches, page, n); init_kmem_cache_node(n); atomic_long_inc(&n->nr_slabs); add_partial(n, page); From 0aa817f078b655d0ae36669169d73a5c8a388016 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 16 May 2007 22:11:01 -0700 Subject: [PATCH 12/34] Slab allocators: define common size limitations Currently we have a maze of configuration variables that determine the maximum slab size. Worst of all it seems to vary between SLAB and SLUB. So define a common maximum size for kmalloc. For conveniences sake we use the maximum size ever supported which is 32 MB. We limit the maximum size to a lower limit if MAX_ORDER does not allow such large allocations. For many architectures this patch will have the effect of adding large kmalloc sizes. x86_64 adds 5 new kmalloc sizes. So a small amount of memory will be needed for these caches (contemporary SLAB has dynamically sizeable node and cpu structure so the waste is less than in the past) Most architectures will then be able to allocate object with sizes up to MAX_ORDER. We have had repeated breakage (in fact whenever we doubled the number of supported processors) on IA64 because one or the other struct grew beyond what the slab allocators supported. This will avoid future issues and f.e. avoid fixes for 2k and 4k cpu support. CONFIG_LARGE_ALLOCS is no longer necessary so drop it. It fixes sparc64 with SLAB. Signed-off-by: Christoph Lameter Signed-off-by: "David S. Miller" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/blackfin/Kconfig | 8 -------- arch/frv/Kconfig | 8 -------- arch/m68knommu/Kconfig | 8 -------- arch/v850/Kconfig | 8 -------- include/linux/kmalloc_sizes.h | 20 +++++++++++++++----- include/linux/slab.h | 15 +++++++++++++++ include/linux/slub_def.h | 19 ++----------------- mm/slab.c | 19 ++----------------- 8 files changed, 34 insertions(+), 71 deletions(-) diff --git a/arch/blackfin/Kconfig b/arch/blackfin/Kconfig index 1a49305093257..d80e5b1d686e2 100644 --- a/arch/blackfin/Kconfig +++ b/arch/blackfin/Kconfig @@ -560,14 +560,6 @@ endchoice source "mm/Kconfig" -config LARGE_ALLOCS - bool "Allow allocating large blocks (> 1MB) of memory" - help - Allow the slab memory allocator to keep chains for very large - memory sizes - upto 32MB. You may need this if your system has - a lot of RAM, and you need to able to allocate very large - contiguous chunks. If unsure, say N. - config BFIN_DMA_5XX bool "Enable DMA Support" depends on (BF533 || BF532 || BF531 || BF537 || BF536 || BF534 || BF561) diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig index 114738a455828..74eef7111f2bd 100644 --- a/arch/frv/Kconfig +++ b/arch/frv/Kconfig @@ -102,14 +102,6 @@ config HIGHPTE with a lot of RAM, this can be wasteful of precious low memory. Setting this option will put user-space page tables in high memory. -config LARGE_ALLOCS - bool "Allow allocating large blocks (> 1MB) of memory" - help - Allow the slab memory allocator to keep chains for very large memory - sizes - up to 32MB. You may need this if your system has a lot of - RAM, and you need to able to allocate very large contiguous chunks. - If unsure, say N. - source "mm/Kconfig" choice diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index 823f73736bb5b..adc64a2bafbbd 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig @@ -470,14 +470,6 @@ config AVNET default y depends on (AVNET5282) -config LARGE_ALLOCS - bool "Allow allocating large blocks (> 1MB) of memory" - help - Allow the slab memory allocator to keep chains for very large - memory sizes - upto 32MB. You may need this if your system has - a lot of RAM, and you need to able to allocate very large - contiguous chunks. If unsure, say N. - config 4KSTACKS bool "Use 4Kb for kernel stacks instead of 8Kb" default y diff --git a/arch/v850/Kconfig b/arch/v850/Kconfig index 5f54c1236c18d..ace479ab273ff 100644 --- a/arch/v850/Kconfig +++ b/arch/v850/Kconfig @@ -240,14 +240,6 @@ menu "Processor type and features" config RESET_GUARD bool "Reset Guard" - config LARGE_ALLOCS - bool "Allow allocating large blocks (> 1MB) of memory" - help - Allow the slab memory allocator to keep chains for very large - memory sizes - upto 32MB. You may need this if your system has - a lot of RAM, and you need to able to allocate very large - contiguous chunks. If unsure, say N. - source "mm/Kconfig" endmenu diff --git a/include/linux/kmalloc_sizes.h b/include/linux/kmalloc_sizes.h index bda23e00ed710..e576b848ce10f 100644 --- a/include/linux/kmalloc_sizes.h +++ b/include/linux/kmalloc_sizes.h @@ -19,17 +19,27 @@ CACHE(32768) CACHE(65536) CACHE(131072) -#if (NR_CPUS > 512) || (MAX_NUMNODES > 256) || !defined(CONFIG_MMU) +#if KMALLOC_MAX_SIZE >= 262144 CACHE(262144) #endif -#ifndef CONFIG_MMU +#if KMALLOC_MAX_SIZE >= 524288 CACHE(524288) +#endif +#if KMALLOC_MAX_SIZE >= 1048576 CACHE(1048576) -#ifdef CONFIG_LARGE_ALLOCS +#endif +#if KMALLOC_MAX_SIZE >= 2097152 CACHE(2097152) +#endif +#if KMALLOC_MAX_SIZE >= 4194304 CACHE(4194304) +#endif +#if KMALLOC_MAX_SIZE >= 8388608 CACHE(8388608) +#endif +#if KMALLOC_MAX_SIZE >= 16777216 CACHE(16777216) +#endif +#if KMALLOC_MAX_SIZE >= 33554432 CACHE(33554432) -#endif /* CONFIG_LARGE_ALLOCS */ -#endif /* CONFIG_MMU */ +#endif diff --git a/include/linux/slab.h b/include/linux/slab.h index 6fb2ae214152b..a015236cc572b 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -73,6 +73,21 @@ static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep, } #endif +/* + * The largest kmalloc size supported by the slab allocators is + * 32 megabyte (2^25) or the maximum allocatable page order if that is + * less than 32 MB. + * + * WARNING: Its not easy to increase this value since the allocators have + * to do various tricks to work around compiler limitations in order to + * ensure proper constant folding. + */ +#define KMALLOC_SHIFT_HIGH ((MAX_ORDER + PAGE_SHIFT) <= 25 ? \ + (MAX_ORDER + PAGE_SHIFT) : 25) + +#define KMALLOC_MAX_SIZE (1UL << KMALLOC_SHIFT_HIGH) +#define KMALLOC_MAX_ORDER (KMALLOC_SHIFT_HIGH - PAGE_SHIFT) + /* * Common kmalloc functions provided by all allocators */ diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index a9fb92862aaa3..0764c829d967a 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -58,17 +58,6 @@ struct kmem_cache { */ #define KMALLOC_SHIFT_LOW 3 -#ifdef CONFIG_LARGE_ALLOCS -#define KMALLOC_SHIFT_HIGH ((MAX_ORDER + PAGE_SHIFT) =< 25 ? \ - (MAX_ORDER + PAGE_SHIFT - 1) : 25) -#else -#if !defined(CONFIG_MMU) || NR_CPUS > 512 || MAX_NUMNODES > 256 -#define KMALLOC_SHIFT_HIGH 20 -#else -#define KMALLOC_SHIFT_HIGH 18 -#endif -#endif - /* * We keep the general caches in an array of slab caches that are used for * 2^x bytes of allocations. @@ -79,7 +68,7 @@ extern struct kmem_cache kmalloc_caches[KMALLOC_SHIFT_HIGH + 1]; * Sorry that the following has to be that ugly but some versions of GCC * have trouble with constant propagation and loops. */ -static inline int kmalloc_index(int size) +static inline int kmalloc_index(size_t size) { /* * We should return 0 if size == 0 but we use the smallest object @@ -87,7 +76,7 @@ static inline int kmalloc_index(int size) */ WARN_ON_ONCE(size == 0); - if (size > (1 << KMALLOC_SHIFT_HIGH)) + if (size > KMALLOC_MAX_SIZE) return -1; if (size > 64 && size <= 96) @@ -110,17 +99,13 @@ static inline int kmalloc_index(int size) if (size <= 64 * 1024) return 16; if (size <= 128 * 1024) return 17; if (size <= 256 * 1024) return 18; -#if KMALLOC_SHIFT_HIGH > 18 if (size <= 512 * 1024) return 19; if (size <= 1024 * 1024) return 20; -#endif -#if KMALLOC_SHIFT_HIGH > 20 if (size <= 2 * 1024 * 1024) return 21; if (size <= 4 * 1024 * 1024) return 22; if (size <= 8 * 1024 * 1024) return 23; if (size <= 16 * 1024 * 1024) return 24; if (size <= 32 * 1024 * 1024) return 25; -#endif return -1; /* diff --git a/mm/slab.c b/mm/slab.c index 1dc0ce1d0d5dd..528243e15cc80 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -568,21 +568,6 @@ static void **dbg_userword(struct kmem_cache *cachep, void *objp) #endif -/* - * Maximum size of an obj (in 2^order pages) and absolute limit for the gfp - * order. - */ -#if defined(CONFIG_LARGE_ALLOCS) -#define MAX_OBJ_ORDER 13 /* up to 32Mb */ -#define MAX_GFP_ORDER 13 /* up to 32Mb */ -#elif defined(CONFIG_MMU) -#define MAX_OBJ_ORDER 5 /* 32 pages */ -#define MAX_GFP_ORDER 5 /* 32 pages */ -#else -#define MAX_OBJ_ORDER 8 /* up to 1Mb */ -#define MAX_GFP_ORDER 8 /* up to 1Mb */ -#endif - /* * Do not go above this order unless 0 objects fit into the slab. */ @@ -2002,7 +1987,7 @@ static size_t calculate_slab_order(struct kmem_cache *cachep, size_t left_over = 0; int gfporder; - for (gfporder = 0; gfporder <= MAX_GFP_ORDER; gfporder++) { + for (gfporder = 0; gfporder <= KMALLOC_MAX_ORDER; gfporder++) { unsigned int num; size_t remainder; @@ -2148,7 +2133,7 @@ kmem_cache_create (const char *name, size_t size, size_t align, * Sanity checks... these are all serious usage bugs. */ if (!name || in_interrupt() || (size < BYTES_PER_WORD) || - (size > (1 << MAX_OBJ_ORDER) * PAGE_SIZE) || dtor) { + size > KMALLOC_MAX_SIZE || dtor) { printk(KERN_ERR "%s: Early error in slab %s\n", __FUNCTION__, name); BUG(); From f363d16fbb9374c0bd7f2757d412c287169094c9 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Wed, 16 May 2007 22:11:06 -0700 Subject: [PATCH 13/34] acpi: fix potential call to a freed memory section. Strip __cpuinit[data] from Node <-> PXM routines and supporting data structures. Also make pxm_to_node_map and node_to_pxm_map local to the numa acpi module. This fixes a bug triggered by the following conditions: - boot on a machine with a SLIT table defined - kernel is configured w/ CONFIG_HOTPLUG_CPU=n - cat /sys/devices/system/node/node*/distance This will cause an oops by calling into a freed memory section. In particular, on x86_64, __node_distance calls node_to_pxm(). Signed-off-by: Aaron Durbin Cc: Len Brown Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/acpi/numa.c | 8 ++++---- include/acpi/acpi_numa.h | 7 ++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index 8fcd6a15517f5..a2efae8a4c4ee 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -40,19 +40,19 @@ static nodemask_t nodes_found_map = NODE_MASK_NONE; #define NID_INVAL -1 /* maps to convert between proximity domain and logical node ID */ -int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS] +static int pxm_to_node_map[MAX_PXM_DOMAINS] = { [0 ... MAX_PXM_DOMAINS - 1] = NID_INVAL }; -int __cpuinitdata node_to_pxm_map[MAX_NUMNODES] +static int node_to_pxm_map[MAX_NUMNODES] = { [0 ... MAX_NUMNODES - 1] = PXM_INVAL }; -int __cpuinit pxm_to_node(int pxm) +int pxm_to_node(int pxm) { if (pxm < 0) return NID_INVAL; return pxm_to_node_map[pxm]; } -int __cpuinit node_to_pxm(int node) +int node_to_pxm(int node) { if (node < 0) return PXM_INVAL; diff --git a/include/acpi/acpi_numa.h b/include/acpi/acpi_numa.h index f9d2bde9a7bba..b62cd36ff3247 100644 --- a/include/acpi/acpi_numa.h +++ b/include/acpi/acpi_numa.h @@ -11,11 +11,8 @@ #define MAX_PXM_DOMAINS (256) /* Old pxm spec is defined 8 bit */ #endif -extern int __cpuinitdata pxm_to_node_map[MAX_PXM_DOMAINS]; -extern int __cpuinitdata node_to_pxm_map[MAX_NUMNODES]; - -extern int __cpuinit pxm_to_node(int); -extern int __cpuinit node_to_pxm(int); +extern int pxm_to_node(int); +extern int node_to_pxm(int); extern int __cpuinit acpi_map_pxm_to_node(int); extern void __cpuinit acpi_unmap_pxm_to_node(int); From df652fe173c12d29960f3a8eafce29041e86b942 Mon Sep 17 00:00:00 2001 From: Bernhard Walle Date: Wed, 16 May 2007 22:11:06 -0700 Subject: [PATCH 14/34] i386/x86-64: fix section mismatch WARNING: arch/x86_64/kernel/built-in.o - Section mismatch: reference to .init.text:mtrr_bp_init from .text between 'id entify_cpu' (at offset 0x6571) and 'IRQ0x20_interrupt' It's because identify_cpu() which is __cpuinit calls mtrr_bp_init() which is __init(). __cpuinit() expands to nothing if CONFIG_HOTPLUG_CPU=y and so the call is illegal. Signed-off-by: Bernhard Walle Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/mtrr/generic.c | 2 +- arch/i386/kernel/cpu/mtrr/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c index 5367e32e04032..c4ebb5126ef7a 100644 --- a/arch/i386/kernel/cpu/mtrr/generic.c +++ b/arch/i386/kernel/cpu/mtrr/generic.c @@ -78,7 +78,7 @@ static void __cpuinit print_fixed(unsigned base, unsigned step, const mtrr_type* } /* Grab all of the MTRR state for this CPU into *state */ -void __init get_mtrr_state(void) +void get_mtrr_state(void) { unsigned int i; struct mtrr_var_range *vrs; diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c index 02a2f39e5e0a3..1cf466df330ad 100644 --- a/arch/i386/kernel/cpu/mtrr/main.c +++ b/arch/i386/kernel/cpu/mtrr/main.c @@ -639,7 +639,7 @@ static struct sysdev_driver mtrr_sysdev_driver = { * initialized (i.e. before smp_init()). * */ -void __init mtrr_bp_init(void) +void mtrr_bp_init(void) { init_ifs(); From d55e2ca87321b65387d3c52dd38128b3fe6723b0 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 16 May 2007 22:11:07 -0700 Subject: [PATCH 15/34] Make __vunmap static __vunmap doesn't seem to be used outside of mm/vmalloc.c, and has no prototype in any header so let's make it static Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index faa2a521dea32..d3a9c5368257a 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -311,7 +311,7 @@ struct vm_struct *remove_vm_area(void *addr) return v; } -void __vunmap(void *addr, int deallocate_pages) +static void __vunmap(void *addr, int deallocate_pages) { struct vm_struct *area; From 8317f14b60c02c69cf7f594e2aabc8a3fdc9618d Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 16 May 2007 22:11:08 -0700 Subject: [PATCH 16/34] simplify compat_sys_timerfd Just thought this is easier to read. Acked-by: Davide Libenzi Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/compat.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/fs/compat.c b/fs/compat.c index 7b21b0a82596f..1de2331db8445 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -2230,21 +2230,16 @@ asmlinkage long compat_sys_signalfd(int ufd, asmlinkage long compat_sys_timerfd(int ufd, int clockid, int flags, const struct compat_itimerspec __user *utmr) { - long res; struct itimerspec t; struct itimerspec __user *ut; - res = -EFAULT; if (get_compat_itimerspec(&t, utmr)) - goto err_exit; + return -EFAULT; ut = compat_alloc_user_space(sizeof(*ut)); - if (copy_to_user(ut, &t, sizeof(t)) ) - goto err_exit; + if (copy_to_user(ut, &t, sizeof(t))) + return -EFAULT; - res = sys_timerfd(ufd, clockid, flags, ut); -err_exit: - return res; + return sys_timerfd(ufd, clockid, flags, ut); } #endif /* CONFIG_TIMERFD */ - From 79974a0e4c6be6e9a3717b4c5a5d5c44c36b1653 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 16 May 2007 22:11:09 -0700 Subject: [PATCH 17/34] Let smp_call_function_single return -EBUSY on UP All architectures that have an implementation of smp_call_function_single let it return -EBUSY if it is asked to execute func on the current cpu. (akpm: except for x86_64). Therefore the UP version must always return -EBUSY. [akpm@linux-foundation.org: build fix] Signed-off-by: Heiko Carstens Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/smp.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/include/linux/smp.h b/include/linux/smp.h index 3f70149eabbb2..96ac21f8dd735 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -6,6 +6,7 @@ * Alan Cox. */ +#include extern void cpu_idle(void); @@ -99,11 +100,9 @@ static inline void smp_send_reschedule(int cpu) { } #define num_booting_cpus() 1 #define smp_prepare_boot_cpu() do {} while (0) static inline int smp_call_function_single(int cpuid, void (*func) (void *info), - void *info, int retry, int wait) + void *info, int retry, int wait) { - /* Disable interrupts here? */ - func(info); - return 0; + return -EBUSY; } #endif /* !SMP */ From a1a4849c419337f649c6633219b555eb4d4d955a Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 16 May 2007 22:11:09 -0700 Subject: [PATCH 18/34] Refine SCREEN_INFO sanity check for vgacon initialization Refine SCREEN_INFO sanity check for vgacon initialization. Checking video mode field only to see whenever SCREEN_INFO is initialized is not enougth, in some cases it is zero although a vga card is present. Lets additionally check cols and lines. Signed-off-by: Gerd Hoffmann Cc: Rusty Russell Cc: Andi Kleen Cc: Alan Cc: Ingo Molnar Acked-by: Eric W. Biederman Cc: "H. Peter Anvin" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/vgacon.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 2460b82a1d932..f46fe95f69fbf 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -368,9 +368,14 @@ static const char *vgacon_startup(void) #endif } + /* SCREEN_INFO initialized? */ + if ((ORIG_VIDEO_MODE == 0) && + (ORIG_VIDEO_LINES == 0) && + (ORIG_VIDEO_COLS == 0)) + goto no_vga; + /* VGA16 modes are not handled by VGACON */ - if ((ORIG_VIDEO_MODE == 0x00) || /* SCREEN_INFO not initialized */ - (ORIG_VIDEO_MODE == 0x0D) || /* 320x200/4 */ + if ((ORIG_VIDEO_MODE == 0x0D) || /* 320x200/4 */ (ORIG_VIDEO_MODE == 0x0E) || /* 640x200/4 */ (ORIG_VIDEO_MODE == 0x10) || /* 640x350/4 */ (ORIG_VIDEO_MODE == 0x12) || /* 640x480/4 */ From e3dfd2964ea86ae65f511b10d62ea54d46db3708 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Wed, 16 May 2007 22:11:11 -0700 Subject: [PATCH 19/34] make freezeable workqueues singlethread It is a known fact that freezeable multithreaded workqueues doesn't like CPU_DEAD. We keep them only for the incoming CPU-hotplug rework. Sadly, we can't just kill create_freezeable_workqueue() right now, make them singlethread. Signed-off-by: Oleg Nesterov Cc: "Rafael J. Wysocki" Cc: Gautham R Shenoy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/workqueue.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index d555f31c0746a..7eae8665ff597 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -122,7 +122,7 @@ extern struct workqueue_struct *__create_workqueue(const char *name, int singlethread, int freezeable); #define create_workqueue(name) __create_workqueue((name), 0, 0) -#define create_freezeable_workqueue(name) __create_workqueue((name), 0, 1) +#define create_freezeable_workqueue(name) __create_workqueue((name), 1, 1) #define create_singlethread_workqueue(name) __create_workqueue((name), 1, 0) extern void destroy_workqueue(struct workqueue_struct *wq); From 3dd1a32968d5e4cc61d4f7e3dc396ed0faca6984 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 16 May 2007 22:11:12 -0700 Subject: [PATCH 20/34] parport: mailing list is subscribers-only linux-parport is subscribers-only: Your mail to 'Linux-parport' with the subject Re: [QUESTION] parallel console configuration Is being held until the list moderator can review it for approval. The reason it is being held: Post by non-member to a members-only list Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index bbeb5b6b5b05b..4c3277cb925e7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2689,13 +2689,13 @@ L: i2c@lm-sensors.org S: Maintained PARALLEL PORT SUPPORT -L: linux-parport@lists.infradead.org +L: linux-parport@lists.infradead.org (subscribers-only) S: Orphan PARIDE DRIVERS FOR PARALLEL PORT IDE DEVICES P: Tim Waugh M: tim@cyberelk.net -L: linux-parport@lists.infradead.org +L: linux-parport@lists.infradead.org (subscribers-only) W: http://www.torque.net/linux-pp.html S: Maintained From 621e59a771f310358ade8f14cb745d5d5f1c410e Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 16 May 2007 22:11:12 -0700 Subject: [PATCH 21/34] docbook: make kernel-locking table readable Andi Kleen pointed out to me that the kernel locking cheat sheet table entries are unreadable. Make table entries smaller so that pdf and ps output is readable (columns were being overwritten and garbled) by using abbreviations. This allows the tables to fit on one page cleanly. Add a Legend for the abbreviations: SLIS: spin_lock_irqsave SLI: spin_lock_irq SL: spin_lock SLBH: spin_lock_bh DI: down_interruptible Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DocBook/kernel-locking.tmpl | 123 ++++++++++++++-------- 1 file changed, 78 insertions(+), 45 deletions(-) diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl index 644c3884fab94..0a441f73261a3 100644 --- a/Documentation/DocBook/kernel-locking.tmpl +++ b/Documentation/DocBook/kernel-locking.tmpl @@ -551,10 +551,12 @@ spin_lock_irqsave(), which is a superset of all other spinlock primitives. + Table of Locking Requirements + IRQ Handler A @@ -576,97 +578,128 @@ IRQ Handler B -spin_lock_irqsave +SLIS None Softirq A -spin_lock_irq -spin_lock_irq -spin_lock +SLI +SLI +SL Softirq B -spin_lock_irq -spin_lock_irq -spin_lock -spin_lock +SLI +SLI +SL +SL Tasklet A -spin_lock_irq -spin_lock_irq -spin_lock -spin_lock +SLI +SLI +SL +SL None Tasklet B -spin_lock_irq -spin_lock_irq -spin_lock -spin_lock -spin_lock +SLI +SLI +SL +SL +SL None Timer A -spin_lock_irq -spin_lock_irq -spin_lock -spin_lock -spin_lock -spin_lock +SLI +SLI +SL +SL +SL +SL None Timer B -spin_lock_irq -spin_lock_irq -spin_lock -spin_lock -spin_lock -spin_lock -spin_lock +SLI +SLI +SL +SL +SL +SL +SL None User Context A -spin_lock_irq -spin_lock_irq -spin_lock_bh -spin_lock_bh -spin_lock_bh -spin_lock_bh -spin_lock_bh -spin_lock_bh +SLI +SLI +SLBH +SLBH +SLBH +SLBH +SLBH +SLBH None User Context B +SLI +SLI +SLBH +SLBH +SLBH +SLBH +SLBH +SLBH +DI +None + + + + +
+ + +Legend for Locking Requirements Table + + + + +SLIS +spin_lock_irqsave + + +SLI spin_lock_irq -spin_lock_irq -spin_lock_bh -spin_lock_bh -spin_lock_bh -spin_lock_bh -spin_lock_bh + + +SL +spin_lock + + +SLBH spin_lock_bh + + +DI down_interruptible -None
+ From 83c6590cb83d3106df12fee36ac2a261951b8c88 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 16 May 2007 22:11:13 -0700 Subject: [PATCH 22/34] gpio interface loosens call restrictions Loosen gpio_{request,free}() and gpio_direction_{in,out}put() call context restrictions slightly, so a common idiom is no longer an error: board init code setting up spinlock-safe GPIOs before tasking is enabled. The issue was caught by some paranoid code with might_sleep() checks. The legacy platform-specific GPIO interfaces stick to spinlock-safe GPIOs, so this change reflects current implementations and won't break anything. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/gpio.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt index e8be0abb346c1..36af58eba136b 100644 --- a/Documentation/gpio.txt +++ b/Documentation/gpio.txt @@ -111,7 +111,9 @@ setting up a platform_device using the GPIO, is mark its direction: The return value is zero for success, else a negative errno. It should be checked, since the get/set calls don't have error returns and since -misconfiguration is possible. (These calls could sleep.) +misconfiguration is possible. You should normally issue these calls from +a task context. However, for spinlock-safe GPIOs it's OK to use them +before tasking is enabled, as part of early board setup. For output GPIOs, the value provided becomes the initial output value. This helps avoid signal glitching during system startup. @@ -197,7 +199,9 @@ However, many platforms don't currently support this mechanism. Passing invalid GPIO numbers to gpio_request() will fail, as will requesting GPIOs that have already been claimed with that call. The return value of -gpio_request() must be checked. (These calls could sleep.) +gpio_request() must be checked. You should normally issue these calls from +a task context. However, for spinlock-safe GPIOs it's OK to request GPIOs +before tasking is enabled, as part of early board setup. These calls serve two basic purposes. One is marking the signals which are actually in use as GPIOs, for better diagnostics; systems may have From 558a40f708bbfb1b260d605cca6c3b9d2c86453e Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 16 May 2007 22:11:14 -0700 Subject: [PATCH 23/34] rtc-omap build fix Fix typo which breaks build. How did that happen? Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-omap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 60a8a4bb8bd28..a2f84f1695887 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -371,7 +371,7 @@ static int __devinit omap_rtc_probe(struct platform_device *pdev) goto fail; } platform_set_drvdata(pdev, rtc); - dev_set_devdata(&rtc->dev, mem); + dev_set_drvdata(&rtc->dev, mem); /* clear pending irqs, and set 1/second periodic, * which we'll use instead of update irqs @@ -453,7 +453,7 @@ static int __devexit omap_rtc_remove(struct platform_device *pdev) free_irq(omap_rtc_timer, rtc); free_irq(omap_rtc_alarm, rtc); - release_resource(dev_get_devdata(&rtc->dev)); + release_resource(dev_get_drvdata(&rtc->dev)); rtc_device_unregister(rtc); return 0; } From e40659c5cae2397d6a329e652aa2d4f1c9f7de2a Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 16 May 2007 22:11:15 -0700 Subject: [PATCH 24/34] rtc kconfig clarification Make drivers/rtc/Kconfig be clearer about what the various "interfaces" actually mean, by showing path names. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 95ce8f49e382a..4e4c10a7fd3a2 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -59,7 +59,7 @@ comment "RTC interfaces" depends on RTC_CLASS config RTC_INTF_SYSFS - boolean "sysfs" + boolean "/sys/class/rtc/rtcN (sysfs)" depends on RTC_CLASS && SYSFS default RTC_CLASS help @@ -70,7 +70,7 @@ config RTC_INTF_SYSFS will be called rtc-sysfs. config RTC_INTF_PROC - boolean "proc" + boolean "/proc/driver/rtc (procfs for rtc0)" depends on RTC_CLASS && PROC_FS default RTC_CLASS help @@ -82,7 +82,7 @@ config RTC_INTF_PROC will be called rtc-proc. config RTC_INTF_DEV - boolean "dev" + boolean "/dev/rtcN (character devices)" depends on RTC_CLASS default RTC_CLASS help From bc88d5d4e18add7283770ead2734b601c50b3e2a Mon Sep 17 00:00:00 2001 From: wendy xiong Date: Wed, 16 May 2007 22:11:16 -0700 Subject: [PATCH 25/34] icom: add new sub-device-id to support new adapter This patch add new sub-device-id to support new adapter and changed the interrupt irq number for unsigned char to unsigned int. [akpm@osdl.org: fix whitespace in device table] Signed-off by: Wendy Xiong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/serial/icom.c | 55 +++++++++++++++++++++++------------------ include/linux/pci_ids.h | 1 + 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index 6202995e82115..9d3105b64a7a5 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c @@ -69,33 +69,40 @@ static const struct pci_device_id icom_pci_table[] = { { - .vendor = PCI_VENDOR_ID_IBM, - .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = ADAPTER_V1, - }, + .vendor = PCI_VENDOR_ID_IBM, + .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .driver_data = ADAPTER_V1, + }, { - .vendor = PCI_VENDOR_ID_IBM, - .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2, - .subvendor = PCI_VENDOR_ID_IBM, - .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX, - .driver_data = ADAPTER_V2, - }, + .vendor = PCI_VENDOR_ID_IBM, + .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2, + .subvendor = PCI_VENDOR_ID_IBM, + .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX, + .driver_data = ADAPTER_V2, + }, { - .vendor = PCI_VENDOR_ID_IBM, - .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2, - .subvendor = PCI_VENDOR_ID_IBM, - .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM, - .driver_data = ADAPTER_V2, - }, + .vendor = PCI_VENDOR_ID_IBM, + .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2, + .subvendor = PCI_VENDOR_ID_IBM, + .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM, + .driver_data = ADAPTER_V2, + }, { - .vendor = PCI_VENDOR_ID_IBM, - .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2, - .subvendor = PCI_VENDOR_ID_IBM, - .subdevice = PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL, - .driver_data = ADAPTER_V2, - }, + .vendor = PCI_VENDOR_ID_IBM, + .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2, + .subvendor = PCI_VENDOR_ID_IBM, + .subdevice = PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL, + .driver_data = ADAPTER_V2, + }, + { + .vendor = PCI_VENDOR_ID_IBM, + .device = PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2, + .subvendor = PCI_VENDOR_ID_IBM, + .subdevice = PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE, + .driver_data = ADAPTER_V2, + }, {} }; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 3b1fbf49fa7d0..62b3e008e6412 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -471,6 +471,7 @@ #define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2 0x0219 #define PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX 0x021A #define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM 0x0251 +#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361 #define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL 0x252 #define PCI_VENDOR_ID_COMPEX2 0x101a /* pci.ids says "AT&T GIS (NCR)" */ From 71ce92f3fa442069670a52fa6230a6064c4517b3 Mon Sep 17 00:00:00 2001 From: Dan Aloni Date: Wed, 16 May 2007 22:11:16 -0700 Subject: [PATCH 26/34] make sysctl/kernel/core_pattern and fs/exec.c agree on maximum core filename size Make sysctl/kernel/core_pattern and fs/exec.c agree on maximum core filename size and change it to 128, so that extensive patterns such as '/local/cores/%e-%h-%s-%t-%p.core' won't result in truncated filename generation. Signed-off-by: Dan Aloni Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 4 +--- include/linux/binfmts.h | 2 ++ kernel/sysctl.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index 70fa36554c142..0b685888ff6f9 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -60,7 +60,7 @@ #endif int core_uses_pid; -char core_pattern[128] = "core"; +char core_pattern[CORENAME_MAX_SIZE] = "core"; int suid_dumpable = 0; EXPORT_SYMBOL(suid_dumpable); @@ -1264,8 +1264,6 @@ int set_binfmt(struct linux_binfmt *new) EXPORT_SYMBOL(set_binfmt); -#define CORENAME_MAX_SIZE 64 - /* format_corename will inspect the pattern parameter, and output a * name into corename, which must have space for at least * CORENAME_MAX_SIZE bytes plus one byte for the zero terminator. diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 2d956cd566aed..e1a708337be35 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -17,6 +17,8 @@ struct pt_regs; #ifdef __KERNEL__ +#define CORENAME_MAX_SIZE 128 + /* * This structure is used to hold the arguments that are used when loading binaries. */ diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 4073353abd4f8..30ee462ee79f8 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -227,7 +227,7 @@ static ctl_table kern_table[] = { .ctl_name = KERN_CORE_PATTERN, .procname = "core_pattern", .data = core_pattern, - .maxlen = 128, + .maxlen = CORENAME_MAX_SIZE, .mode = 0644, .proc_handler = &proc_dostring, .strategy = &sysctl_string, From c9f2875b7968453a852e1de5d3504fd2241e8989 Mon Sep 17 00:00:00 2001 From: Nate Diller Date: Wed, 16 May 2007 22:11:17 -0700 Subject: [PATCH 27/34] ecryptfs: use zero_user_page Use zero_user_page() instead of open-coding it. Signed-off-by: Nate Diller Cc: Michael Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ecryptfs/mmap.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c index 0770c4b66f53d..88ea6697908f5 100644 --- a/fs/ecryptfs/mmap.c +++ b/fs/ecryptfs/mmap.c @@ -364,18 +364,14 @@ static int fill_zeros_to_end_of_page(struct page *page, unsigned int to) { struct inode *inode = page->mapping->host; int end_byte_in_page; - char *page_virt; if ((i_size_read(inode) / PAGE_CACHE_SIZE) != page->index) goto out; end_byte_in_page = i_size_read(inode) % PAGE_CACHE_SIZE; if (to > end_byte_in_page) end_byte_in_page = to; - page_virt = kmap_atomic(page, KM_USER0); - memset((page_virt + end_byte_in_page), 0, - (PAGE_CACHE_SIZE - end_byte_in_page)); - kunmap_atomic(page_virt, KM_USER0); - flush_dcache_page(page); + zero_user_page(page, end_byte_in_page, + PAGE_CACHE_SIZE - end_byte_in_page, KM_USER0); out: return 0; } @@ -740,7 +736,6 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros) { int rc = 0; struct page *tmp_page; - char *tmp_page_virt; tmp_page = ecryptfs_get1page(file, index); if (IS_ERR(tmp_page)) { @@ -757,10 +752,7 @@ int write_zeros(struct file *file, pgoff_t index, int start, int num_zeros) page_cache_release(tmp_page); goto out; } - tmp_page_virt = kmap_atomic(tmp_page, KM_USER0); - memset(((char *)tmp_page_virt + start), 0, num_zeros); - kunmap_atomic(tmp_page_virt, KM_USER0); - flush_dcache_page(tmp_page); + zero_user_page(tmp_page, start, num_zeros, KM_USER0); rc = ecryptfs_commit_write(file, tmp_page, start, start + num_zeros); if (rc < 0) { ecryptfs_printk(KERN_ERR, "Error attempting to write zero's " From bb49b32fece7910fbb02a6934bca4495596f6c8c Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Wed, 16 May 2007 22:11:18 -0700 Subject: [PATCH 28/34] i386: don't check_pgt_cache in flush_tlb_mm No other architecture calls check_pgt_cache() from within flush_tlb_mm(), and i386 is already calling check_pgt_cache() from the usual places, tlb_finish_mmu() and cpu_idle() (the latter being odd, but not unusual). flush_tlb_mm() has no business to be freeing pages: remove that line, which sneaked in with slub's i386 support. Signed-off-by: Hugh Dickins Cc: Andi Kleen Acked-by: Christoph Lameter Acked-by: William Lee Irwin III Cc: David Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index c9a7c9835aba8..6299c080f6e2e 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -421,7 +421,7 @@ void flush_tlb_mm (struct mm_struct * mm) } if (!cpus_empty(cpu_mask)) flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL); - check_pgt_cache(); + preempt_enable(); } From 7925409e202a41176b729671eab6e610a54153cd Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 16 May 2007 22:11:19 -0700 Subject: [PATCH 29/34] circular locking dependency found in QUOTA OFF i_mutex on quota files is special. Unlike i_mutexes for other inodes it is acquired under dqonoff_mutex. Tell lockdep about this lock ranking. Also comment and code in quota_sync_sb() seem to be bogus (as i_mutex for quota file can be acquired under dqonoff_mutex). Move truncate_inode_pages() call under dqonoff_mutex and save some problems with races... Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/dquot.c | 2 +- fs/quota.c | 23 +++++++---------------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/fs/dquot.c b/fs/dquot.c index 3a995841de90e..8819d281500c9 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -1421,7 +1421,7 @@ int vfs_quota_off(struct super_block *sb, int type) /* If quota was reenabled in the meantime, we have * nothing to do */ if (!sb_has_quota_enabled(sb, cnt)) { - mutex_lock(&toputinode[cnt]->i_mutex); + mutex_lock_nested(&toputinode[cnt]->i_mutex, I_MUTEX_QUOTA); toputinode[cnt]->i_flags &= ~(S_IMMUTABLE | S_NOATIME | S_NOQUOTA); truncate_inode_pages(&toputinode[cnt]->i_data, 0); diff --git a/fs/quota.c b/fs/quota.c index e9d88fd0eca8f..9f237d6182c90 100644 --- a/fs/quota.c +++ b/fs/quota.c @@ -157,7 +157,6 @@ static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t static void quota_sync_sb(struct super_block *sb, int type) { int cnt; - struct inode *discard[MAXQUOTAS]; sb->s_qcop->quota_sync(sb, type); /* This is not very clever (and fast) but currently I don't know about @@ -167,29 +166,21 @@ static void quota_sync_sb(struct super_block *sb, int type) sb->s_op->sync_fs(sb, 1); sync_blockdev(sb->s_bdev); - /* Now when everything is written we can discard the pagecache so - * that userspace sees the changes. We need i_mutex and so we could - * not do it inside dqonoff_mutex. Moreover we need to be carefull - * about races with quotaoff() (that is the reason why we have own - * reference to inode). */ + /* + * Now when everything is written we can discard the pagecache so + * that userspace sees the changes. + */ mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - discard[cnt] = NULL; if (type != -1 && cnt != type) continue; if (!sb_has_quota_enabled(sb, cnt)) continue; - discard[cnt] = igrab(sb_dqopt(sb)->files[cnt]); + mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex, I_MUTEX_QUOTA); + truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0); + mutex_unlock(&sb_dqopt(sb)->files[cnt]->i_mutex); } mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); - for (cnt = 0; cnt < MAXQUOTAS; cnt++) { - if (discard[cnt]) { - mutex_lock(&discard[cnt]->i_mutex); - truncate_inode_pages(&discard[cnt]->i_data, 0); - mutex_unlock(&discard[cnt]->i_mutex); - iput(discard[cnt]); - } - } } void sync_dquots(struct super_block *sb, int type) From 8d98a690f58e0d6ecf424b7ca84488475cf87bd9 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 16 May 2007 22:11:19 -0700 Subject: [PATCH 30/34] swsusp: fix sysfs interface The sysfs files /sys/power/disk and /sys/power/state do not work as documented, since they allow the user to write only a few initial characters of the input string to trigger the option (eg. 'echo pl > /sys/power/disk' activates the platform mode of hibernation). Fix it. Special thanks to Peter Moulder for pointing out the problem. Signed-off-by: Rafael J. Wysocki Acked-by: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/power/disk.c | 3 ++- kernel/power/main.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/power/disk.c b/kernel/power/disk.c index b5f0543ed84d3..f445b9cd60fbd 100644 --- a/kernel/power/disk.c +++ b/kernel/power/disk.c @@ -416,7 +416,8 @@ static ssize_t disk_store(struct kset *kset, const char *buf, size_t n) mutex_lock(&pm_mutex); for (i = HIBERNATION_FIRST; i <= HIBERNATION_MAX; i++) { - if (!strncmp(buf, hibernation_modes[i], len)) { + if (len == strlen(hibernation_modes[i]) + && !strncmp(buf, hibernation_modes[i], len)) { mode = i; break; } diff --git a/kernel/power/main.c b/kernel/power/main.c index b98b80ccf4373..8812985f30296 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -290,13 +290,13 @@ static ssize_t state_store(struct kset *kset, const char *buf, size_t n) len = p ? p - buf : n; /* First, check if we are requested to hibernate */ - if (!strncmp(buf, "disk", len)) { + if (len == 4 && !strncmp(buf, "disk", len)) { error = hibernate(); return error ? error : n; } for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) { - if (*s && !strncmp(buf, *s, len)) + if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) break; } if (state < PM_SUSPEND_MAX && *s) From ea125892a17f43919c726777ed1e4929d41e7984 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Wed, 16 May 2007 22:11:21 -0700 Subject: [PATCH 31/34] Fix page allocation flags in grow_dev_page() grow_dev_page() simply passes GFP_NOFS to find_or_create_page. This means the allocation of radix tree nodes is done with GFP_NOFS and the allocation of a new page is done using GFP_NOFS. The mapping has a flags field that contains the necessary allocation flags for the page cache allocation. These need to be consulted in order to get DMA and HIGHMEM allocations etc right. And yes a blockdev could be allowing Highmem allocations if its a ramdisk. Cc: Hugh Dickins Signed-off-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/buffer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/buffer.c b/fs/buffer.c index 3deeb886f6e6f..49590d590d7db 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -981,7 +981,8 @@ grow_dev_page(struct block_device *bdev, sector_t block, struct page *page; struct buffer_head *bh; - page = find_or_create_page(inode->i_mapping, index, GFP_NOFS); + page = find_or_create_page(inode->i_mapping, index, + mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); if (!page) return NULL; From c97a9e10eaee328e6eea9f76acf7bacd7d48ef56 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 16 May 2007 22:11:21 -0700 Subject: [PATCH 32/34] mm: more rmap checking Re-introduce rmap verification patches that Hugh removed when he removed PG_map_lock. PG_map_lock actually isn't needed to synchronise access to anonymous pages, because PG_locked and PTL together already do. These checks were important in discovering and fixing a rare rmap corruption in SLES9. Signed-off-by: Nick Piggin Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/rmap.h | 13 ++++------ mm/memory.c | 2 +- mm/rmap.c | 58 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 62 insertions(+), 11 deletions(-) diff --git a/include/linux/rmap.h b/include/linux/rmap.h index bdd277223af01..97347f22fc207 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -74,17 +74,14 @@ void page_add_new_anon_rmap(struct page *, struct vm_area_struct *, unsigned lon void page_add_file_rmap(struct page *); void page_remove_rmap(struct page *, struct vm_area_struct *); -/** - * page_dup_rmap - duplicate pte mapping to a page - * @page: the page to add the mapping to - * - * For copy_page_range only: minimal extract from page_add_rmap, - * avoiding unnecessary tests (already checked) so it's quicker. - */ -static inline void page_dup_rmap(struct page *page) +#ifdef CONFIG_DEBUG_VM +void page_dup_rmap(struct page *page, struct vm_area_struct *vma, unsigned long address); +#else +static inline void page_dup_rmap(struct page *page, struct vm_area_struct *vma, unsigned long address) { atomic_inc(&page->_mapcount); } +#endif /* * Called from mm/vmscan.c to handle paging out diff --git a/mm/memory.c b/mm/memory.c index 1d647ab0ee72d..cb94488ab96da 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -481,7 +481,7 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, page = vm_normal_page(vma, addr, pte); if (page) { get_page(page); - page_dup_rmap(page); + page_dup_rmap(page, vma, addr); rss[!!PageAnon(page)]++; } diff --git a/mm/rmap.c b/mm/rmap.c index 1c1af92732d50..850165d32b7a1 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -529,20 +529,52 @@ static void __page_set_anon_rmap(struct page *page, __inc_zone_page_state(page, NR_ANON_PAGES); } +/** + * page_set_anon_rmap - sanity check anonymous rmap addition + * @page: the page to add the mapping to + * @vma: the vm area in which the mapping is added + * @address: the user virtual address mapped + */ +static void __page_check_anon_rmap(struct page *page, + struct vm_area_struct *vma, unsigned long address) +{ +#ifdef CONFIG_DEBUG_VM + /* + * The page's anon-rmap details (mapping and index) are guaranteed to + * be set up correctly at this point. + * + * We have exclusion against page_add_anon_rmap because the caller + * always holds the page locked, except if called from page_dup_rmap, + * in which case the page is already known to be setup. + * + * We have exclusion against page_add_new_anon_rmap because those pages + * are initially only visible via the pagetables, and the pte is locked + * over the call to page_add_new_anon_rmap. + */ + struct anon_vma *anon_vma = vma->anon_vma; + anon_vma = (void *) anon_vma + PAGE_MAPPING_ANON; + BUG_ON(page->mapping != (struct address_space *)anon_vma); + BUG_ON(page->index != linear_page_index(vma, address)); +#endif +} + /** * page_add_anon_rmap - add pte mapping to an anonymous page * @page: the page to add the mapping to * @vma: the vm area in which the mapping is added * @address: the user virtual address mapped * - * The caller needs to hold the pte lock. + * The caller needs to hold the pte lock and the page must be locked. */ void page_add_anon_rmap(struct page *page, struct vm_area_struct *vma, unsigned long address) { + VM_BUG_ON(!PageLocked(page)); + VM_BUG_ON(address < vma->vm_start || address >= vma->vm_end); if (atomic_inc_and_test(&page->_mapcount)) __page_set_anon_rmap(page, vma, address); - /* else checking page index and mapping is racy */ + else + __page_check_anon_rmap(page, vma, address); } /* @@ -553,10 +585,12 @@ void page_add_anon_rmap(struct page *page, * * Same as page_add_anon_rmap but must only be called on *new* pages. * This means the inc-and-test can be bypassed. + * Page does not have to be locked. */ void page_add_new_anon_rmap(struct page *page, struct vm_area_struct *vma, unsigned long address) { + BUG_ON(address < vma->vm_start || address >= vma->vm_end); atomic_set(&page->_mapcount, 0); /* elevate count by 1 (starts at -1) */ __page_set_anon_rmap(page, vma, address); } @@ -573,6 +607,26 @@ void page_add_file_rmap(struct page *page) __inc_zone_page_state(page, NR_FILE_MAPPED); } +#ifdef CONFIG_DEBUG_VM +/** + * page_dup_rmap - duplicate pte mapping to a page + * @page: the page to add the mapping to + * + * For copy_page_range only: minimal extract from page_add_file_rmap / + * page_add_anon_rmap, avoiding unnecessary tests (already checked) so it's + * quicker. + * + * The caller needs to hold the pte lock. + */ +void page_dup_rmap(struct page *page, struct vm_area_struct *vma, unsigned long address) +{ + BUG_ON(page_mapcount(page) == 0); + if (PageAnon(page)) + __page_check_anon_rmap(page, vma, address); + atomic_inc(&page->_mapcount); +} +#endif + /** * page_remove_rmap - take down pte mapping from a page * @page: page to remove mapping from From b5b82df6f461e66af821bff5b51f336af92d96b6 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 17 May 2007 14:27:39 +0800 Subject: [PATCH 33/34] NS16550A: Restore HS settings in EXCR2 on resume After a suspend/resume cycle, the UART may have been reset into low-speed mode -- either because it's actually been reset, or because the firmware pokes at the old-style divisor registers. If we detected it as a NS16550A SuperIO chip in the first place and set baud_base to 921600, then we should do so again in the resume path. This patch adds that code to serial8250_resume_port(), and also makes serial8250_resume() actually call serial8250_resume_port() for each port instead of just calling uart_resume_port() directly. And thus fixes serial port operation after suspend/resume. It also fixes a bogus comment where we write the EXCR2 register with a comment saying /* EXCR1 */ Signed-off-by: David Woodhouse Acked-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/serial/8250.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 48e259a0167d1..c84dab083a852 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -894,7 +894,7 @@ static void autoconfig_16550a(struct uart_8250_port *up) quot = serial_dl_read(up); quot <<= 3; - status1 = serial_in(up, 0x04); /* EXCR1 */ + status1 = serial_in(up, 0x04); /* EXCR2 */ status1 &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ status1 |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ serial_outp(up, 0x04, status1); @@ -2617,7 +2617,22 @@ void serial8250_suspend_port(int line) */ void serial8250_resume_port(int line) { - uart_resume_port(&serial8250_reg, &serial8250_ports[line].port); + struct uart_8250_port *up = &serial8250_ports[line]; + + if (up->capabilities & UART_NATSEMI) { + unsigned char tmp; + + /* Ensure it's still in high speed mode */ + serial_outp(up, UART_LCR, 0xE0); + + tmp = serial_in(up, 0x04); /* EXCR2 */ + tmp &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */ + tmp |= 0x10; /* 1.625 divisor for baud_base --> 921600 */ + serial_outp(up, 0x04, tmp); + + serial_outp(up, UART_LCR, 0); + } + uart_resume_port(&serial8250_reg, &up->port); } /* @@ -2694,7 +2709,7 @@ static int serial8250_resume(struct platform_device *dev) struct uart_8250_port *up = &serial8250_ports[i]; if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) - uart_resume_port(&serial8250_reg, &up->port); + serial8250_resume_port(i); } return 0; From 0479ea0eab197b3e5d4c731f526c02e5e3fbfbd0 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Thu, 17 May 2007 18:48:12 +0800 Subject: [PATCH 34/34] Fix incorrect prototype for ipxrtr_route_packet() The function ipxrtr_route_packet() takes a 'len' argument of type size_t. However, its prototype in af_ipx.c incorrectly suggests that the corresponding argument is of type 'int' instead. Discovered by building with --combine and letting the compiler see it all at once. Signed-off-by: David Woodhouse Signed-off-by: Linus Torvalds --- net/ipx/af_ipx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 15419dd682fda..8400525177ab4 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -87,7 +87,7 @@ extern int ipxrtr_add_route(__be32 network, struct ipx_interface *intrfc, unsigned char *node); extern void ipxrtr_del_routes(struct ipx_interface *intrfc); extern int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, - struct iovec *iov, int len, int noblock); + struct iovec *iov, size_t len, int noblock); extern int ipxrtr_route_skb(struct sk_buff *skb); extern struct ipx_route *ipxrtr_lookup(__be32 net); extern int ipxrtr_ioctl(unsigned int cmd, void __user *arg);