From 7cc68973c36d92c493fc07ff38df6347f85a532e Mon Sep 17 00:00:00 2001 From: Joonsoo Kim Date: Fri, 18 Apr 2014 16:24:09 +0900 Subject: slab: fix the type of the index on freelist index accessor Commit a41adfaa23df ("slab: introduce byte sized index for the freelist of a slab") changes the size of freelist index and also changes prototype of accessor function to freelist index. And there was a mistake. The mistake is that although it changes the size of freelist index correctly, it changes the size of the index of freelist index incorrectly. With patch, freelist index can be 1 byte or 2 bytes, that means that num of object on on a slab can be more than 255. So we need more than 1 byte for the index to find the index of free object on freelist. But, above patch makes this index type 1 byte, so slab which have more than 255 objects cannot work properly and in consequence of it, the system cannot boot. This issue was reported by Steven King on m68knommu which would use 2 bytes freelist index: https://lkml.org/lkml/2014/4/16/433 To fix is easy. To change the type of the index of freelist index on accessor functions is enough to fix this bug. Although 2 bytes is enough, I use 4 bytes since it have no bad effect and make things more easier. This fix was suggested and tested by Steven in his original report. Signed-off-by: Joonsoo Kim Reported-and-acked-by: Steven King Acked-by: Christoph Lameter Tested-by: James Hogan Tested-by: David Miller Cc: Pekka Enberg Signed-off-by: Linus Torvalds --- mm/slab.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mm/slab.c') diff --git a/mm/slab.c b/mm/slab.c index 388cb1ae6fbc..d7f9f4494054 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -2572,13 +2572,13 @@ static void *alloc_slabmgmt(struct kmem_cache *cachep, return freelist; } -static inline freelist_idx_t get_free_obj(struct page *page, unsigned char idx) +static inline freelist_idx_t get_free_obj(struct page *page, unsigned int idx) { return ((freelist_idx_t *)page->freelist)[idx]; } static inline void set_free_obj(struct page *page, - unsigned char idx, freelist_idx_t val) + unsigned int idx, freelist_idx_t val) { ((freelist_idx_t *)(page->freelist))[idx] = val; } -- cgit v1.2.3-55-g7522 From 30321c7b658a5661eea715b33e82a5fd3e33e180 Mon Sep 17 00:00:00 2001 From: David Miller Date: Mon, 5 May 2014 16:20:04 -0400 Subject: slab: Fix off by one in object max number tests. If freelist_idx_t is a byte, SLAB_OBJ_MAX_NUM should be 255 not 256, and likewise if freelist_idx_t is a short, then it should be 65535 not 65536. This was leading to all kinds of random crashes on sparc64 where PAGE_SIZE is 8192. One problem shown was that if spinlock debugging was enabled, we'd get deadlocks in copy_pte_range() or do_wp_page() with the same cpu already holding a lock it shouldn't hold, or the lock belonging to a completely unrelated process. Fixes: a41adfaa23df ("slab: introduce byte sized index for the freelist of a slab") Signed-off-by: David S. Miller Signed-off-by: Linus Torvalds --- mm/slab.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mm/slab.c') diff --git a/mm/slab.c b/mm/slab.c index d7f9f4494054..19d92181ce24 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -166,7 +166,7 @@ typedef unsigned char freelist_idx_t; typedef unsigned short freelist_idx_t; #endif -#define SLAB_OBJ_MAX_NUM (1 << sizeof(freelist_idx_t) * BITS_PER_BYTE) +#define SLAB_OBJ_MAX_NUM ((1 << sizeof(freelist_idx_t) * BITS_PER_BYTE) - 1) /* * true if a page was allocated from pfmemalloc reserves for network-based -- cgit v1.2.3-55-g7522