From: Christoph Lameter <clameter@sgi.com>
To: Christoph Hellwig <hch@lst.de>, Mel Gorman <mel@skynet.ie>
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: David Chinner <dgc@sgi.com>, Jens Axboe <jens.axboe@oracle.com>
Subject: [15/17] SLUB: Support virtual fallback via SLAB_VFALLBACK
Date: Tue, 18 Sep 2007 20:36:20 -0700 [thread overview]
Message-ID: <20070919033643.763818012@sgi.com> (raw)
In-Reply-To: 20070919033605.785839297@sgi.com
[-- Attachment #1: vcompound_slub_support --]
[-- Type: text/plain, Size: 8705 bytes --]
SLAB_VFALLBACK can be specified for selected slab caches. If fallback is
available then the conservative settings for higher order allocations are
overridden. We then request an order that can accomodate at mininum
100 objects. The size of an individual slab allocation is allowed to reach
up to 256k (order 6 on i386, order 4 on IA64).
Implementing fallback requires special handling of virtual mappings in
the free path. However, the impact is minimal since we already check the
address if its NULL or ZERO_SIZE_PTR. No additional cachelines are
touched if we do not fall back. However, if we need to handle a virtual
compound page then walk the kernel page table in the free paths to
determine the page struct.
We also need special handling in the allocation paths since the virtual
addresses cannot be obtained via page_address(). SLUB exploits that
page->private is set to the vmalloc address to avoid a costly
vmalloc_address().
However, for diagnostics there is still the need to determine the
vmalloc address from the page struct. There we must use the costly
vmalloc_address().
Signed-off-by: Christoph Lameter <clameter@sgi.com>
---
include/linux/slab.h | 1
include/linux/slub_def.h | 1
mm/slub.c | 83 ++++++++++++++++++++++++++++++++---------------
3 files changed, 60 insertions(+), 25 deletions(-)
Index: linux-2.6/include/linux/slab.h
===================================================================
--- linux-2.6.orig/include/linux/slab.h 2007-09-18 17:03:30.000000000 -0700
+++ linux-2.6/include/linux/slab.h 2007-09-18 17:07:39.000000000 -0700
@@ -19,6 +19,7 @@
* The ones marked DEBUG are only valid if CONFIG_SLAB_DEBUG is set.
*/
#define SLAB_DEBUG_FREE 0x00000100UL /* DEBUG: Perform (expensive) checks on free */
+#define SLAB_VFALLBACK 0x00000200UL /* May fall back to vmalloc */
#define SLAB_RED_ZONE 0x00000400UL /* DEBUG: Red zone objs in a cache */
#define SLAB_POISON 0x00000800UL /* DEBUG: Poison objects */
#define SLAB_HWCACHE_ALIGN 0x00002000UL /* Align objs on cache lines */
Index: linux-2.6/mm/slub.c
===================================================================
--- linux-2.6.orig/mm/slub.c 2007-09-18 17:03:30.000000000 -0700
+++ linux-2.6/mm/slub.c 2007-09-18 18:13:38.000000000 -0700
@@ -20,6 +20,7 @@
#include <linux/mempolicy.h>
#include <linux/ctype.h>
#include <linux/kallsyms.h>
+#include <linux/vmalloc.h>
/*
* Lock order:
@@ -277,6 +278,26 @@ static inline struct kmem_cache_node *ge
#endif
}
+static inline void *slab_address(struct page *page)
+{
+ if (unlikely(PageVcompound(page)))
+ return vmalloc_address(page);
+ else
+ return page_address(page);
+}
+
+static inline struct page *virt_to_slab(const void *addr)
+{
+ struct page *page;
+
+ if (unlikely(is_vmalloc_addr(addr)))
+ page = vmalloc_to_page(addr);
+ else
+ page = virt_to_page(addr);
+
+ return compound_head(page);
+}
+
static inline int check_valid_pointer(struct kmem_cache *s,
struct page *page, const void *object)
{
@@ -285,7 +306,7 @@ static inline int check_valid_pointer(st
if (!object)
return 1;
- base = page_address(page);
+ base = slab_address(page);
if (object < base || object >= base + s->objects * s->size ||
(object - base) % s->size) {
return 0;
@@ -470,7 +491,7 @@ static void slab_fix(struct kmem_cache *
static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
{
unsigned int off; /* Offset of last byte */
- u8 *addr = page_address(page);
+ u8 *addr = slab_address(page);
print_tracking(s, p);
@@ -648,7 +669,7 @@ static int slab_pad_check(struct kmem_ca
if (!(s->flags & SLAB_POISON))
return 1;
- start = page_address(page);
+ start = slab_address(page);
end = start + (PAGE_SIZE << s->order);
length = s->objects * s->size;
remainder = end - (start + length);
@@ -1040,11 +1061,7 @@ static struct page *allocate_slab(struct
struct page * page;
int pages = 1 << s->order;
- if (s->order)
- flags |= __GFP_COMP;
-
- if (s->flags & SLAB_CACHE_DMA)
- flags |= SLUB_DMA;
+ flags |= s->gfpflags;
if (node == -1)
page = alloc_pages(flags, s->order);
@@ -1098,7 +1115,11 @@ static struct page *new_slab(struct kmem
SLAB_STORE_USER | SLAB_TRACE))
SetSlabDebug(page);
- start = page_address(page);
+ if (!PageVcompound(page))
+ start = slab_address(page);
+ else
+ start = (void *)page->private;
+
end = start + s->objects * s->size;
if (unlikely(s->flags & SLAB_POISON))
@@ -1130,7 +1151,7 @@ static void __free_slab(struct kmem_cach
void *p;
slab_pad_check(s, page);
- for_each_object(p, s, page_address(page))
+ for_each_object(p, s, slab_address(page))
check_object(s, page, p, 0);
ClearSlabDebug(page);
}
@@ -1672,7 +1693,7 @@ void kmem_cache_free(struct kmem_cache *
{
struct page *page;
- page = virt_to_head_page(x);
+ page = virt_to_slab(x);
slab_free(s, page, x, __builtin_return_address(0));
}
@@ -1681,7 +1702,7 @@ EXPORT_SYMBOL(kmem_cache_free);
/* Figure out on which slab object the object resides */
static struct page *get_object_page(const void *x)
{
- struct page *page = virt_to_head_page(x);
+ struct page *page = virt_to_slab(x);
if (!PageSlab(page))
return NULL;
@@ -1780,10 +1801,9 @@ static inline int slab_order(int size, i
return order;
}
-static inline int calculate_order(int size)
+static inline int calculate_order(int size, int min_objects, int max_order)
{
int order;
- int min_objects;
int fraction;
/*
@@ -1794,13 +1814,12 @@ static inline int calculate_order(int si
* First we reduce the acceptable waste in a slab. Then
* we reduce the minimum objects required in a slab.
*/
- min_objects = slub_min_objects;
while (min_objects > 1) {
fraction = 8;
while (fraction >= 4) {
order = slab_order(size, min_objects,
- slub_max_order, fraction);
- if (order <= slub_max_order)
+ max_order, fraction);
+ if (order <= max_order)
return order;
fraction /= 2;
}
@@ -1811,8 +1830,8 @@ static inline int calculate_order(int si
* We were unable to place multiple objects in a slab. Now
* lets see if we can place a single object there.
*/
- order = slab_order(size, 1, slub_max_order, 1);
- if (order <= slub_max_order)
+ order = slab_order(size, 1, max_order, 1);
+ if (order <= max_order)
return order;
/*
@@ -2059,10 +2078,24 @@ static int calculate_sizes(struct kmem_c
size = ALIGN(size, align);
s->size = size;
- s->order = calculate_order(size);
+ if (s->flags & SLAB_VFALLBACK)
+ s->order = calculate_order(size, 100, 18 - PAGE_SHIFT);
+ else
+ s->order = calculate_order(size, slub_min_objects,
+ slub_max_order);
+
if (s->order < 0)
return 0;
+ if (s->order)
+ s->gfpflags |= __GFP_COMP;
+
+ if (s->flags & SLAB_VFALLBACK)
+ s->gfpflags |= __GFP_VFALLBACK;
+
+ if (s->flags & SLAB_CACHE_DMA)
+ s->flags |= SLUB_DMA;
+
/*
* Determine the number of objects per slab
*/
@@ -2477,7 +2510,7 @@ void kfree(const void *x)
if (ZERO_OR_NULL_PTR(x))
return;
- page = virt_to_head_page(x);
+ page = virt_to_slab(x);
s = page->slab;
slab_free(s, page, (void *)x, __builtin_return_address(0));
@@ -2806,7 +2839,7 @@ static int validate_slab(struct kmem_cac
unsigned long *map)
{
void *p;
- void *addr = page_address(page);
+ void *addr = slab_address(page);
if (!check_slab(s, page) ||
!on_freelist(s, page, NULL))
@@ -3048,7 +3081,7 @@ static int add_location(struct loc_track
cpu_set(track->cpu, l->cpus);
}
- node_set(page_to_nid(virt_to_page(track)), l->nodes);
+ node_set(page_to_nid(virt_to_slab(track)), l->nodes);
return 1;
}
@@ -3079,14 +3112,14 @@ static int add_location(struct loc_track
cpus_clear(l->cpus);
cpu_set(track->cpu, l->cpus);
nodes_clear(l->nodes);
- node_set(page_to_nid(virt_to_page(track)), l->nodes);
+ node_set(page_to_nid(virt_to_slab(track)), l->nodes);
return 1;
}
static void process_slab(struct loc_track *t, struct kmem_cache *s,
struct page *page, enum track_item alloc)
{
- void *addr = page_address(page);
+ void *addr = slab_address(page);
DECLARE_BITMAP(map, s->objects);
void *p;
Index: linux-2.6/include/linux/slub_def.h
===================================================================
--- linux-2.6.orig/include/linux/slub_def.h 2007-09-18 17:03:30.000000000 -0700
+++ linux-2.6/include/linux/slub_def.h 2007-09-18 17:07:39.000000000 -0700
@@ -31,6 +31,7 @@ struct kmem_cache {
int objsize; /* The size of an object without meta data */
int offset; /* Free pointer offset. */
int order;
+ int gfpflags; /* Allocation flags */
/*
* Avoid an extra cache line for UP, SMP and for the node local to
--
next prev parent reply other threads:[~2007-09-19 3:36 UTC|newest]
Thread overview: 111+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-19 3:36 [00/17] [RFC] Virtual Compound Page Support Christoph Lameter
2007-09-19 3:36 ` [01/17] Vmalloc: Move vmalloc_to_page to mm/vmalloc Christoph Lameter
2007-09-19 3:36 ` [02/17] Vmalloc: add const Christoph Lameter
2007-09-19 3:36 ` [03/17] is_vmalloc_addr(): Check if an address is within the vmalloc boundaries Christoph Lameter
2007-09-19 6:32 ` David Rientjes
2007-09-19 7:24 ` Anton Altaparmakov
2007-09-19 8:09 ` David Rientjes
2007-09-19 8:44 ` Anton Altaparmakov
2007-09-19 9:19 ` David Rientjes
2007-09-19 13:23 ` Anton Altaparmakov
2007-09-19 17:29 ` Christoph Lameter
2007-09-19 17:52 ` Anton Altaparmakov
2007-09-19 17:29 ` Christoph Lameter
2007-09-19 17:52 ` Anton Altaparmakov
2007-09-19 3:36 ` [04/17] vmalloc: clean up page array indexing Christoph Lameter
2007-09-19 3:36 ` [05/17] vunmap: return page array Christoph Lameter
2007-09-19 8:05 ` KAMEZAWA Hiroyuki
2007-09-19 22:15 ` Christoph Lameter
2007-09-20 0:47 ` KAMEZAWA Hiroyuki
2007-09-19 3:36 ` [06/17] vmalloc_address(): Determine vmalloc address from page struct Christoph Lameter
2007-09-19 3:36 ` [07/17] GFP_VFALLBACK: Allow fallback of compound pages to virtual mappings Christoph Lameter
2007-09-19 3:36 ` [08/17] Pass vmalloc address in page->private Christoph Lameter
2007-09-19 3:36 ` [09/17] VFALLBACK: Debugging aid Christoph Lameter
2007-09-19 3:36 ` [10/17] Use GFP_VFALLBACK for sparsemem Christoph Lameter
2007-09-19 3:36 ` [11/17] GFP_VFALLBACK for zone wait table Christoph Lameter
2007-09-19 3:36 ` [12/17] Virtual Compound page allocation from interrupt context Christoph Lameter
2007-09-19 3:36 ` [13/17] Virtual compound page freeing in " Christoph Lameter
2007-09-18 20:36 ` Nick Piggin
2007-09-20 17:50 ` Christoph Lameter
2007-09-19 3:36 ` [14/17] Allow bit_waitqueue to wait on a bit in a vmalloc area Christoph Lameter
2007-09-19 4:12 ` Gabriel C
2007-09-19 17:40 ` Christoph Lameter
2007-09-19 3:36 ` Christoph Lameter [this message]
2007-09-27 21:42 ` [15/17] SLUB: Support virtual fallback via SLAB_VFALLBACK Nick Piggin
2007-09-28 17:33 ` Christoph Lameter
2007-09-28 5:14 ` Nick Piggin
2007-10-01 20:50 ` Christoph Lameter
2007-10-02 8:43 ` Nick Piggin
2007-10-04 16:16 ` SLUB performance regression vs SLAB Matthew Wilcox
2007-10-04 17:38 ` Christoph Lameter
2007-10-04 17:50 ` Arjan van de Ven
2007-10-04 17:58 ` Christoph Lameter
2007-10-04 18:26 ` Peter Zijlstra
2007-10-04 20:48 ` David Miller
2007-10-04 20:58 ` Matthew Wilcox
2007-10-04 21:05 ` David Miller
2007-10-04 21:11 ` Christoph Lameter
2007-10-04 18:32 ` Matthew Wilcox
2007-10-04 17:49 ` Christoph Lameter
2007-10-04 19:28 ` Matthew Wilcox
2007-10-04 19:05 ` Christoph Lameter
2007-10-04 19:46 ` Siddha, Suresh B
2007-10-04 20:55 ` David Miller
2007-10-04 21:02 ` Chuck Ebbert
2007-10-04 21:11 ` David Miller
2007-10-04 21:47 ` Chuck Ebbert
2007-10-04 22:07 ` David Miller
2007-10-04 22:23 ` David Chinner
2007-10-05 6:48 ` Jens Axboe
2007-10-05 9:19 ` Pekka Enberg
2007-10-05 9:28 ` Jens Axboe
2007-10-05 11:12 ` Andi Kleen
2007-10-05 12:39 ` Jens Axboe
2007-10-05 19:31 ` Christoph Lameter
2007-10-05 19:32 ` Christoph Lameter
2007-10-05 11:56 ` Matthew Wilcox
2007-10-05 12:37 ` Jens Axboe
2007-10-05 19:27 ` Christoph Lameter
2007-10-05 20:32 ` Peter Zijlstra
2007-10-05 21:31 ` David Miller
2007-10-04 21:05 ` Matthew Wilcox
2007-10-05 2:43 ` Christoph Lameter
2007-10-05 2:53 ` Arjan van de Ven
2007-09-28 17:55 ` [15/17] SLUB: Support virtual fallback via SLAB_VFALLBACK Peter Zijlstra
2007-09-28 18:20 ` Christoph Lameter
2007-09-28 18:25 ` Peter Zijlstra
2007-09-28 18:41 ` Christoph Lameter
2007-09-28 20:22 ` Nick Piggin
2007-09-28 21:14 ` Mel Gorman
2007-09-28 20:59 ` Mel Gorman
2007-09-29 8:13 ` Andrew Morton
2007-09-29 8:47 ` Peter Zijlstra
2007-09-29 8:53 ` Peter Zijlstra
2007-09-29 9:01 ` Andrew Morton
2007-09-29 9:14 ` Peter Zijlstra
2007-09-29 9:27 ` Andrew Morton
2007-09-28 20:19 ` Nick Piggin
2007-09-29 19:20 ` Andrew Morton
2007-09-29 19:09 ` Nick Piggin
2007-09-30 20:12 ` Andrew Morton
2007-09-30 4:16 ` Nick Piggin
2007-09-29 9:00 ` Andrew Morton
2007-10-01 20:55 ` Christoph Lameter
2007-10-01 21:30 ` Andrew Morton
2007-10-01 21:38 ` Christoph Lameter
2007-10-01 21:45 ` Andrew Morton
2007-10-01 21:52 ` Christoph Lameter
2007-10-02 9:19 ` Peter Zijlstra
2007-09-29 8:45 ` Peter Zijlstra
2007-10-01 21:01 ` Christoph Lameter
2007-10-02 8:37 ` Nick Piggin
2007-09-28 21:05 ` Mel Gorman
2007-10-01 21:10 ` Christoph Lameter
2007-09-19 3:36 ` [16/17] Allow virtual fallback for buffer_heads Christoph Lameter
2007-09-19 3:36 ` [17/17] Allow virtual fallback for dentries Christoph Lameter
2007-09-19 7:34 ` [00/17] [RFC] Virtual Compound Page Support Anton Altaparmakov
2007-09-19 8:34 ` Eric Dumazet
2007-09-19 17:33 ` Christoph Lameter
2007-09-19 8:24 ` Andi Kleen
2007-09-19 17:36 ` Christoph Lameter
-- strict thread matches above, loose matches on Subject: below --
2007-09-25 23:42 [00/17] Virtual Compound Page Support V1 Christoph Lameter
2007-09-25 23:42 ` [15/17] SLUB: Support virtual fallback via SLAB_VFALLBACK Christoph Lameter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070919033643.763818012@sgi.com \
--to=clameter@sgi.com \
--cc=hch@lst.de \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mel@skynet.ie \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).