Slab defragmentation V6
Subsystems (13)
cover Slab defragmentation V6
Slab defragmentation is mainly an issue if Linux is used as a fileserver and large amounts of dentries, inodes and buffer heads accumulate. In some load situations the slabs become very sparsely populated so that a lot of memory is wasted by slabs that only contain one or a few objects. In extreme cases the performance of a machine will become sluggish since we are continually running reclaim. Slab defragmentation adds the capability to recover wasted memory.
With lumpy reclaim slab defragmentation can be used to enhance the ability to recover larger contiguous areas of memory. Lumpy reclaim currently cannot do anything if a slab page is encountered. With slab defragmentation that slab page can be removed and a large contiguous page freed. It may be possible to have slab pages also part of ZONE_MOVABLE (Mel's defrag scheme in 2.6.23) or the MOVABLE areas (antifrag patches in mm).
The patchset is also available via git
git pull git://git.kernel.org/pub/scm/linux/kernel/git/christoph/slab.git defrag
Currently memory reclaim from the following slab caches is possible:
1. dentry cache
2. inode cache (with a generic interface to allow easy setup of more filesystems than the currently supported ext2/3/4 reiserfs, XFS and proc)
3. buffer_heads
One typical mechanism that triggers slab defragmentation on my systems is the daily run of
updatedb
Updatedb scans all files on the system which causes a high inode and dentry use. After updatedb is complete we need to go back to the regular use patterns (typical on my machine: kernel compiles). Those need the memory now for different purposes. The inodes and dentries used for updatedb will gradually be aged by the dentry/inode reclaim algorithm which will free up the dentries and inode entries randomly through the slabs that were allocated. As a result the slabs will become sparsely populated. If they become empty then they can be freed but a lot of them will remain sparsely populated. That is where slab defrag comes in: It removes the slabs with just a few entries reclaiming more memory for other uses.
V5->V6
- Rediff against 2.6.24-rc2 + mm slub patches.
- Add reviewed by lines.
- Take out the experimental code to make slab pages movable. That has to wait until this has been considered by Mel.
V4->V5:
- Support lumpy reclaim for slabs
- Support reclaim via slab_shrink()
- Add constructors to insure a consistent object state at all times.
V3->V4:
- Optimize scan for slabs that need defragmentation
- Add /sys/slab/*/defrag_ratio to allow setting defrag limits per slab.
- Add support for buffer heads.
- Describe how the cleanup after the daily updatedb can be improved by slab defragmentation.
V2->V3
- Support directory reclaim
- Add infrastructure to trigger defragmentation after slab shrinking if we have slabs with a high degree of fragmentation.
V1->V2
- Clean up control flow using a state variable. Simplify API. Back to 2 functions that now take arrays of objects.
- Inode defrag support for a set of filesystems
- Fix up dentry defrag support to work on negative dentries by adding a new dentry flag that indicates that a dentry is not in the process of being freed or allocated.
PATCH 1/23 SLUB: Move count_partial()
Move the counting function for objects in partial slabs so that it is placed before kmem_cache_shrink. We will need to use it to establish the fragmentation ratio of per node slab lists.
[This patch is already in mm]
--- mm/slub.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
mm/slub.c +13 -13
@@ -2758,6 +2758,19 @@ void kfree(const void *x) }EXPORT_SYMBOL (kfree); +static unsigned long count_partial (struct kmem_cache_node *n) +{ +unsigned long flags; +unsigned long x =0 ; +struct page *page; + +spin_lock_irqsave (&n->list_lock, flags); +list_for_each_entry (page, &n->partial, lru) + x += page->inuse; +spin_unlock_irqrestore (&n->list_lock, flags); +return x; +} +/* * kmem_cache_shrink removes empty slabs from the partial lists and sorts * the remaining slabs by the number of items in use. The slabs with the
@@ -3615,19 +3628,6 @@ static int list_locations(struct kmem_careturn n; } -static unsigned long count_partial (struct kmem_cache_node *n) -{ -unsigned long flags; -unsigned long x =0 ; -struct page *page; - -spin_lock_irqsave (&n->list_lock, flags); -list_for_each_entry (page, &n->partial, lru) - x += page->inuse; -spin_unlock_irqrestore (&n->list_lock, flags); -return x; -} -enum slab_stat_type {SL_FULL ,SL_PARTIAL ,
PATCH 2/23 SLUB: Rename NUMA defrag_ratio to remote_node_defrag_ratio
In reply to Christoph LameterWe need the defrag ratio for the non NUMA situation now. The NUMA defrag works by allocating objects from partial slabs on remote nodes. Rename it to
remote_node_defrag_ratio
to be clear about this.
[This patch is already in mm]
--- include/linux/slub_def.h | 5 ++++- mm/slub.c | 17 +++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-)
include/linux/slub_def.h +4 -1
@@ -60,7 +60,10 @@ struct kmem_cache {#endif #ifdef CONFIG_NUMA -int defrag_ratio; +/* +* Defragmentation by allocating from a remote node. +*/ +int remote_node_defrag_ratio;struct kmem_cache_node *node[MAX_NUMNODES ];#endif #ifdef CONFIG_SMP
mm/slub.c +9 -8
@@ -1345,7 +1345,8 @@ static unsigned long get_any_partial(str* expensive if we do it every time we are trying to find a slab * with available objects. */ -if (!s->defrag_ratio ||get_cycles () %1024 > s->defrag_ratio) +if (!s->remote_node_defrag_ratio || +get_cycles () %1024 > s->remote_node_defrag_ratio)return 0 ; zonelist = &NODE_DATA (slab_node (current->mempolicy))
@@ -2363,7 +2364,7 @@ static int kmem_cache_open(struct kmem_c s->refcount =1 ;#ifdef CONFIG_NUMA - s->defrag_ratio =100 ; + s->remote_node_defrag_ratio =100 ;#endif if (!init_kmem_cache_nodes (s, gfpflags & ~SLUB_DMA )) goto error;
@@ -4005,21 +4006,21 @@ static ssize_t free_calls_show(struct kmSLAB_ATTR_RO (free_calls);#ifdef CONFIG_NUMA -static ssize_t defrag_ratio_show (struct kmem_cache *s,char *buf) +static ssize_t remote_node_defrag_ratio_show (struct kmem_cache *s,char *buf) { -return sprintf (buf,"%d\n" , s->defrag_ratio /10 ); +return sprintf (buf,"%d\n" , s->remote_node_defrag_ratio /10 ); } -static ssize_t defrag_ratio_store (struct kmem_cache *s, +static ssize_t remote_node_defrag_ratio_store (struct kmem_cache *s,const char *buf,size_t length) {int n =simple_strtoul (buf,NULL ,10 );if (n <100 ) - s->defrag_ratio = n *10 ; + s->remote_node_defrag_ratio = n *10 ;return length; } -SLAB_ATTR (defrag_ratio); +SLAB_ATTR (remote_node_defrag_ratio);#endif static struct attribute * slab_attrs[] = {
@@ -4050,7 +4051,7 @@ static struct attribute * slab_attrs[] = &cache_dma_attr.attr,#endif #ifdef CONFIG_NUMA - &defrag_ratio_attr.attr, + &remote_node_defrag_ratio_attr.attr, #endifNULL };
Re: [patch 02/23] SLUB: Rename NUMA defrag_ratio to remote_node_defrag_ratio
On (06/11/07 17:11), Christoph Lameter didst pronounce:
Quoted 5 lines
We need the defrag ratio for the non NUMA situation now. The NUMA defrag works by allocating objects from partial slabs on remote nodes. Rename it to
remote_node_defrag_ratio
I'm not too keen on the defrag name here largely because I cannot tell what it has to do with defragmention or ratios. It's really about working out when it is better to pack objects into a remote slab than reclaim objects from a local slab, right? It's also not clear what it is a ratio of what to what. I thought it might be clock cycles but that isn't very clear either. If we are renaming this can it be something like remote_packing_cost_limit ?
Quoted 16 lines
to be clear about this.
[This patch is already in mm]
Reviewed-by Rik van Riel <[email protected]>Signed-off-by Christoph Lameter <[email protected]>--- include/linux/slub_def.h | 5 ++++- mm/slub.c | 17 +++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-)Index:
linux-2.6/include/linux/slub_def.h
===================================================================
include/linux/slub_def.h struct kmem_cache { · line 66
Quoted 8 lines
include/linux/slub_def.h +4
-1@@ -60,7 +60,10 @@ struct kmem_cache {#endif #ifdef CONFIG_NUMA -int defrag_ratio; +/* +* Defragmentation by allocating from a remote node. +*/ +int remote_node_defrag_ratio;
How about
/*
* When packing objects into slabs, it may become necessary to
* reclaim objects on a local slab or allocate from a remote node.
* The remote_packing_cost_limit is the maximum cost of remote
* accesses that should be paid before it becomes worthwhile to
* reclaim instead
*/
int remote_packing_cost_limit;
?
I still don't see what get_cycles() has to do with anything but this could be because my understanding of SLUB sucks.
Quoted 8 lines
include/linux/slub_def.h +0
-0struct kmem_cache_node *node[MAX_NUMNODES ];#endif #ifdef CONFIG_SMP Index:
linux-2.6/mm/slub.c
===================================================================
mm/slub.c static unsigned long get_any_partial(str · line 1349
Quoted 6 lines
mm/slub.c +2
-1@@ -1345,7 +1345,8 @@ static unsigned long get_any_partial(str* expensive if we do it every time we are trying to find a slab * with available objects. */ -if (!s->defrag_ratio ||get_cycles () %1024 > s->defrag_ratio) +if (!s->remote_node_defrag_ratio || +get_cycles () %1024 > s->remote_node_defrag_ratio)
I cannot figure out what the number of cycles currently showing on the TSC have to do with a ratio :(. I could semi-understand if we were counting up how many cycles were being spent trying to pack objects but that does not appear to be the case. The comment didn't help a whole lot either. It felt like a cost for packing, not a ratio
Quoted 51 lines
mm/slub.c +7
-7return 0 ; zonelist = &NODE_DATA (slab_node (current->mempolicy))@@ -2363,7 +2364,7 @@ static int kmem_cache_open(struct kmem_c s->refcount =1 ;#ifdef CONFIG_NUMA - s->defrag_ratio =100 ; + s->remote_node_defrag_ratio =100 ;#endif if (!init_kmem_cache_nodes (s, gfpflags & ~SLUB_DMA )) goto error;@@ -4005,21 +4006,21 @@ static ssize_t free_calls_show(struct kmSLAB_ATTR_RO (free_calls);#ifdef CONFIG_NUMA -static ssize_t defrag_ratio_show (struct kmem_cache *s,char *buf) +static ssize_t remote_node_defrag_ratio_show (struct kmem_cache *s,char *buf) { -return sprintf (buf,"%d\n" , s->defrag_ratio /10 ); +return sprintf (buf,"%d\n" , s->remote_node_defrag_ratio /10 ); } -static ssize_t defrag_ratio_store (struct kmem_cache *s, +static ssize_t remote_node_defrag_ratio_store (struct kmem_cache *s,const char *buf,size_t length) {int n =simple_strtoul (buf,NULL ,10 );if (n <100 ) - s->defrag_ratio = n *10 ; + s->remote_node_defrag_ratio = n *10 ;return length; } -SLAB_ATTR (defrag_ratio); +SLAB_ATTR (remote_node_defrag_ratio);#endif static struct attribute * slab_attrs[] = {@@ -4050,7 +4051,7 @@ static struct attribute * slab_attrs[] = &cache_dma_attr.attr,#endif #ifdef CONFIG_NUMA - &defrag_ratio_attr.attr, + &remote_node_defrag_ratio_attr.attr, #endifNULL };Signature · 1 line
--
Signature · 10 lines
-- Mel Gorman Part-time Phd Student Linux Technology Center University of Limerick IBM Dublin Software Lab -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 02/23] SLUB: Rename NUMA defrag_ratio to remote_node_defrag_ratio
Quoted 9 lines · Mel Gorman
mm/slub.c static unsigned long get_any_partial(str · line 1349
Quoted 3 lines
mm/slub.c +2
-1-if (!s->defrag_ratio ||get_cycles () %1024 > s->defrag_ratio) +if (!s->remote_node_defrag_ratio || +get_cycles () %1024 > s->remote_node_defrag_ratio)I cannot figure out what the number of cycles currently showing on the TSC have to do with a ratio :(. I could semi-understand if we were counting up how many cycles were being spent trying to pack objects but that does not appear to be the case. The comment didn't help a whole lot either. It felt like a cost for packing, not a ratio
It's just a random number generator. And a bad one: lots of arches return 0. And I believe at least one of them has some NUMA support.
Signature · 7 lines
Mathematics is the supreme nostalgia of our time. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 02/23] SLUB: Rename NUMA defrag_ratio to remote_node_defrag_ratio
Quoted 8 lines · Matt Mackall
Quoted 5 lines
I cannot figure out what the number of cycles currently showing on the TSC have to do with a ratio :(. I could semi-understand if we were counting up how many cycles were being spent trying to pack objects but that does not appear to be the case. The comment didn't help a whole lot either. It felt like a cost for packing, not a ratio
It's just a random number generator. And a bad one: lots of arches return 0. And I believe at least one of them has some NUMA support.
Do we have a better one? Something with minimal processing overhead? I'd be glad to switch it.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 02/23] SLUB: Rename NUMA defrag_ratio to remote_node_defrag_ratio
Quoted 8 lines · Christoph Lameter
Quoted 6 lines · Matt Mackall
Quoted 5 lines
I cannot figure out what the number of cycles currently showing on the TSC have to do with a ratio :(. I could semi-understand if we were counting up how many cycles were being spent trying to pack objects but that does not appear to be the case. The comment didn't help a whole lot either. It felt like a cost for packing, not a ratio
Quoted 5 lines
Quoted 2 lines
It's just a random number generator. And a bad one: lots of arches return 0. And I believe at least one of them has some NUMA support.
Do we have a better one? Something with minimal processing overhead? I'd be glad to switch it.
Not really. drivers/char/random.c does:
__get_cpu_var(trickle_count)++ & 0xfff
for a similar purpose.
Signature · 7 lines
Mathematics is the supreme nostalgia of our time. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 02/23] SLUB: Rename NUMA defrag_ratio to remote_node_defrag_ratio
Quoted 3 lines · Matt Mackall
Not really.
drivers/char/random.cdoes:__get_cpu_var(trickle_count)++ &
0xfff
That is incremented on each call to add_timer_randomness. Not a high enough resolution there. I guess I am stuck with get_cycles().
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 02/23] SLUB: Rename NUMA defrag_ratio to remote_node_defrag_ratio
Quoted 8 lines · Christoph Lameter
Quoted 3 lines · Matt Mackall
Not really.
drivers/char/random.cdoes:__get_cpu_var(trickle_count)++ &
0xfffThat is incremented on each call to
add_timer_randomness. Not a high enough resolution there. I guess I am stuck withget_cycles().
I'm not suggesting you use trickle_count, silly. I'm suggesting you use a similar approach.
But perhaps I should just add a lightweight RNG to random.c and be done with it.
Signature · 7 lines
Mathematics is the supreme nostalgia of our time. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 02/23] SLUB: Rename NUMA defrag_ratio to remote_node_defrag_ratio
Quoted 2 lines · Matt Mackall
But perhaps I should just add a lightweight RNG to
random.cand be done with it.
It would be appreciated.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 02/23] SLUB: Rename NUMA defrag_ratio to remote_node_defrag_ratio
Quoted 6 lines · Christoph Lameter
Quoted 2 lines · Matt Mackall
But perhaps I should just add a lightweight RNG to
random.cand be done with it.It would be appreciated.
As someone pointed out privately, there's a random32() in lib/random32.c.
Unfortunately, this function is too heavy for many fast-path uses and too weak for most other uses. I'll see if I can come up with something better..
Signature · 7 lines
Mathematics is the supreme nostalgia of our time. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 02/23] SLUB: Rename NUMA defrag_ratio to remote_node_defrag_ratio
In reply to Mel GormanQuoted 7 lines · Mel Gorman
On (06/11/07 17:11), Christoph Lameter didst pronounce:
Quoted 5 lines
We need the defrag ratio for the non NUMA situation now. The NUMA defrag works by allocating objects from partial slabs on remote nodes. Rename it to
remote_node_defrag_ratio
Quoted 6 lines
I'm not too keen on the defrag name here largely because I cannot tell what it has to do with defragmention or ratios. It's really about working out when it is better to pack objects into a remote slab than reclaim objects from a local slab, right? It's also not clear what it is a ratio of what to what. I thought it might be clock cycles but that isn't very clear either. If we are renaming this can it be something like
remote_packing_cost_limit?
In a NUMA situation we have a choice between
1. Allocating a page from the local node (which consumes more memory and is advantageous performance wise.
2. Not allocating from the local node but see if any other node has available partially allocated slabs. If we allocate from them then we save memory and reduce the amount of partial slabs on the remote node. Thus the fragmentation ratio is reduced.
Quoted 11 lines
How about
/*
* When packing objects into slabs, it may become necessary to
* reclaim objects on a local slab or allocate from a remote node.
* Theremote_packing_cost_limitis the maximum cost of remote
* accesses that should be paid before it becomes worthwhile to
* reclaim instead
*/
intremote_packing_cost_limit;
Quoted 1 line
?
That is not what this is about. And the functionality has been in SLUB since the beginning.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 02/23] SLUB: Rename NUMA defrag_ratio to remote_node_defrag_ratio
On (08/11/07 10:56), Christoph Lameter didst pronounce:
Quoted 18 lines · Mel Gorman
Quoted 8 lines
On (06/11/07 17:11), Christoph Lameter didst pronounce:
Quoted 5 lines
We need the defrag ratio for the non NUMA situation now. The NUMA defrag works by allocating objects from partial slabs on remote nodes. Rename it to
remote_node_defrag_ratioQuoted 6 lines
I'm not too keen on the defrag name here largely because I cannot tell what it has to do with defragmention or ratios. It's really about working out when it is better to pack objects into a remote slab than reclaim objects from a local slab, right? It's also not clear what it is a ratio of what to what. I thought it might be clock cycles but that isn't very clear either. If we are renaming this can it be something like
remote_packing_cost_limit?In a NUMA situation we have a choice between
Quoted 8 lines
1. Allocating a page from the local node (which consumes more memory and is advantageous performance wise.
2. Not allocating from the local node but see if any other node has available partially allocated slabs. If we allocate from them then we save memory and reduce the amount of partial slabs on the remote node. Thus the fragmentation ratio is reduced.
Ok, I get the logic somewhat now, thanks.
Quoted 11 lines
Quoted 11 lines
How about
/*
* When packing objects into slabs, it may become necessary to
* reclaim objects on a local slab or allocate from a remote node.
* Theremote_packing_cost_limitis the maximum cost of remote
* accesses that should be paid before it becomes worthwhile to
* reclaim instead
*/
intremote_packing_cost_limit;
Quoted 5 lines
Quoted 1 line
?
That is not what this is about. And the functionality has been in SLUB since the beginning.
Yeah, my understanding of SLUB is crap. Sorry for the noise.
Signature · 10 lines
-- Mel Gorman Part-time Phd Student Linux Technology Center University of Limerick IBM Dublin Software Lab -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 3/23 bufferhead: Revert constructor removal
In reply to Christoph LameterThe constructor for buffer_head slabs was removed recently. We need the constructor in order to insure that slab objects always have a definite state even before we allocated them.
[This patch is already in mm]
--- fs/buffer.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-)
fs/buffer.c +15 -4
@@ -3169,10 +3169,9 @@ static void recalc_bh_state(void)struct buffer_head *alloc_buffer_head (gfp_t gfp_flags) { -struct buffer_head *ret =kmem_cache_zalloc (bh_cachep, +struct buffer_head *ret =kmem_cache_alloc (bh_cachep,set_migrateflags (gfp_flags, __GFP_RECLAIMABLE));if (ret) { -INIT_LIST_HEAD (&ret->b_assoc_buffers);get_cpu_var (bh_accounting).nr++;recalc_bh_state ();put_cpu_var (bh_accounting);
@@ -3213,12 +3212,24 @@ static int buffer_cpu_notify(struct notireturn NOTIFY_OK ; } +static void +init_buffer_head (void *data,struct kmem_cache *cachep,unsigned long flags) +{ +struct buffer_head * bh = (struct buffer_head *)data; + +memset (bh,0 ,sizeof (*bh)); +INIT_LIST_HEAD (&bh->b_assoc_buffers); +} +void __init buffer_init (void ) {int nrpages; - bh_cachep =KMEM_CACHE (buffer_head, -SLAB_RECLAIM_ACCOUNT |SLAB_PANIC |SLAB_MEM_SPREAD ); + bh_cachep =kmem_cache_create ("buffer_head" , +sizeof (struct buffer_head ),0 , + (SLAB_RECLAIM_ACCOUNT |SLAB_PANIC | +SLAB_MEM_SPREAD ), + init_buffer_head);/* * Limit the bh occupancy to 10% of ZONE_NORMAL
PATCH 4/23 dentries: Extract common code to remove dentry from lru
In reply to Christoph LameterExtract the common code to remove a dentry from the lru into a new function dentry_lru_remove().
Two call sites used list_del() instead of list_del_init(). AFAIK the performance of both is the same. dentry_lru_remove() does a list_del_init().
As a result dentry->d_lru is now always empty when a dentry is freed. A consistent state is useful to establish dentry state from slab defrag.
[This patch is already in mm]
--- fs/dcache.c | 42 ++++++++++++++---------------------------- 1 file changed, 14 insertions(+), 28 deletions(-)
fs/dcache.c +14 -28
@@ -95,6 +95,14 @@ static void d_free(struct dentry *dentrycall_rcu (&dentry->d_u.d_rcu, d_callback); } +static void dentry_lru_remove (struct dentry *dentry) +{ +if (!list_empty (&dentry->d_lru)) { +list_del_init (&dentry->d_lru); + dentry_stat.nr_unused--; + } +} +/* * Release the dentry's inode, using the filesystem * d_iput() operation if defined.
@@ -211,13 +219,7 @@ repeat: unhash_it:__d_drop (dentry); kill_it: -/* If dentry was on d_lru list -* delete it from there -*/ -if (!list_empty (&dentry->d_lru)) { -list_del (&dentry->d_lru); - dentry_stat.nr_unused--; - } +dentry_lru_remove (dentry); dentry =d_kill (dentry);if (dentry) goto repeat;
@@ -285,10 +287,7 @@ int d_invalidate(struct dentry * dentry)static inline struct dentry *__dget_locked (struct dentry *dentry) {atomic_inc (&dentry->d_count); -if (!list_empty (&dentry->d_lru)) { - dentry_stat.nr_unused--; -list_del_init (&dentry->d_lru); - } +dentry_lru_remove (dentry);return dentry; }
@@ -404,10 +403,7 @@ static void prune_one_dentry(struct dentif (dentry->d_op && dentry->d_op->d_delete) dentry->d_op->d_delete (dentry); -if (!list_empty (&dentry->d_lru)) { -list_del (&dentry->d_lru); - dentry_stat.nr_unused--; - } +dentry_lru_remove (dentry);__d_drop (dentry); dentry =d_kill (dentry);spin_lock (&dcache_lock);
@@ -596,10 +592,7 @@ static void shrink_dcache_for_umount_sub/* detach this root from the system */ spin_lock (&dcache_lock); -if (!list_empty (&dentry->d_lru)) { - dentry_stat.nr_unused--; -list_del_init (&dentry->d_lru); - } +dentry_lru_remove (dentry);__d_drop (dentry);spin_unlock (&dcache_lock);
@@ -613,11 +606,7 @@ static void shrink_dcache_for_umount_subspin_lock (&dcache_lock);list_for_each_entry (loop, &dentry->d_subdirs, d_u.d_child) { -if (!list_empty (&loop->d_lru)) { - dentry_stat.nr_unused--; -list_del_init (&loop->d_lru); - } - +dentry_lru_remove (dentry);__d_drop (loop);cond_resched_lock (&dcache_lock); }
@@ -799,10 +788,7 @@ resume: struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child); next = tmp->next; -if (!list_empty (&dentry->d_lru)) { - dentry_stat.nr_unused--; -list_del_init (&dentry->d_lru); - } +dentry_lru_remove (dentry);/* * move only zero ref count dentries to the end * of the unused list for prune_dcache
Re: [patch 04/23] dentries: Extract common code to remove dentry from lru
Hi Christoph,
fs/dcache.c static void shrink_dcache_for_umount_sub · line 609
Quoted 10 lines · Christoph Lameter
fs/dcache.c +1
-5@@ -613,11 +606,7 @@ static void shrink_dcache_for_umount_subspin_lock (&dcache_lock);list_for_each_entry (loop, &dentry->d_subdirs, d_u.d_child) { -if (!list_empty (&loop->d_lru)) { - dentry_stat.nr_unused--; -list_del_init (&loop->d_lru); - } - +dentry_lru_remove (dentry);
Shouldn't this be dentry_lru_remove(loop)?
Hannes
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Jörn Engel
Acked-byRe: [patch 04/23] dentries: Extract common code to remove dentry from lru
Quoted 13 lines · Johannes Weiner
fs/dcache.c static void shrink_dcache_for_umount_sub · line 609
Quoted 10 lines · Christoph Lameter
fs/dcache.c +1
-5@@ -613,11 +606,7 @@ static void shrink_dcache_for_umount_subspin_lock (&dcache_lock);list_for_each_entry (loop, &dentry->d_subdirs, d_u.d_child) { -if (!list_empty (&loop->d_lru)) { - dentry_stat.nr_unused--; -list_del_init (&loop->d_lru); - } - +dentry_lru_remove (dentry);Shouldn't this be
dentry_lru_remove(loop)?
Looks like it. Once this is fixed, feel free to add
JA?rn
Signature · 9 lines
It does not require a majority to prevail, but rather an irate, tireless minority keen to set brush fires in people's minds. -- Samuel Adams -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Christoph Lameter
Acked-by Joern EngelRe: [patch 04/23] dentries: Extract common code to remove dentry from lru
Quoted 2 lines · Jörn Engel
Looks like it. Once this is fixed, feel free to add
Acked-by Joern Engel <[email protected]>
Its in the slab defrag git now. I added the spelling fix and this one as a result of the discussions today.
From: Christoph Lameter <[email protected]>
Subject: dcache: use the correct variable.
We need to use "loop" instead of "dentry"
fs/dcache.c +1 -1
@@ -610,7 +610,7 @@ static void shrink_dcache_for_umount_subspin_lock (&dcache_lock);list_for_each_entry (loop, &dentry->d_subdirs, d_u.d_child) { -dentry_lru_remove (dentry); +dentry_lru_remove (loop);__d_drop (loop);cond_resched_lock (&dcache_lock); }
Re: [patch 04/23] dentries: Extract common code to remove dentry from lru
Quoted 14 lines · Christoph Lameter
From: Christoph Lameter <[email protected]>
Subject: dcache: use the correct variable.We need to use "loop" instead of "dentry"
Acked-by Joern Engel <[email protected]>Signed-off-by Christoph Lameter <[email protected]>Index:
linux-2.6/fs/dcache.c
===================================================================
fs/dcache.c static void shrink_dcache_for_umount_sub · line 616
Quoted 8 lines
fs/dcache.c +1
-1@@ -610,7 +610,7 @@ static void shrink_dcache_for_umount_subspin_lock (&dcache_lock);list_for_each_entry (loop, &dentry->d_subdirs, d_u.d_child) { -dentry_lru_remove (dentry); +dentry_lru_remove (loop);__d_drop (loop);cond_resched_lock (&dcache_lock); }
Erm - wouldn't this break git-bisect?
JA?rn
Signature · 8 lines
Joern's library part 5: http://www.faqs.org/faqs/compression-faq/part2/section-9.html -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 04/23] dentries: Extract common code to remove dentry from lru
Quoted 18 lines · Jörn Engel
Quoted 8 lines
Acked-by Joern Engel <[email protected]>Signed-off-by Christoph Lameter <[email protected]>Index:
linux-2.6/fs/dcache.c
===================================================================fs/dcache.c static void shrink_dcache_for_umount_sub · line 616
Quoted 8 lines
fs/dcache.c +1
-1@@ -610,7 +610,7 @@ static void shrink_dcache_for_umount_subspin_lock (&dcache_lock);list_for_each_entry (loop, &dentry->d_subdirs, d_u.d_child) { -dentry_lru_remove (dentry); +dentry_lru_remove (loop);__d_drop (loop);cond_resched_lock (&dcache_lock); }Erm - wouldn't this break git-bisect?
Well Andrew will merge it into the earlier patch.
Re: [patch 04/23] dentries: Extract common code to remove dentry from lru
In reply to Johannes WeinerQuoted 15 lines · Johannes Weiner
Hi Christoph,
Review static void shrink_dcache_for_umount_sub · line 609
Quoted 10 lines · Christoph Lameter
(quoted diff) +1
-5@@ -613,11 +606,7 @@ static void shrink_dcache_for_umount_sub spin_lock(&dcache_lock); list_for_each_entry(loop, &dentry->d_subdirs, d_u.d_child) { - if (!list_empty(&loop->d_lru)) { - dentry_stat.nr_unused--; - list_del_init(&loop->d_lru); - } - + dentry_lru_remove(dentry);Shouldn't this be
dentry_lru_remove(loop)?
Correct. Andrew: This needs to go into your tree to fix the patch that is already there:
[PATCH] dcache: use the correct variable.
We need to use "loop" instead of "dentry"
fs/dcache.c +1 -1
@@ -610,7 +610,7 @@ static void shrink_dcache_for_umount_subspin_lock (&dcache_lock);list_for_each_entry (loop, &dentry->d_subdirs, d_u.d_child) { -dentry_lru_remove (dentry); +dentry_lru_remove (loop);__d_drop (loop);cond_resched_lock (&dcache_lock); }
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 5/23 VM: Allow get_page_unless_zero on compound pages
In reply to Christoph LameterSLUB uses compound pages for larger slabs. We need to increment the page count of these pages in order to make sure that they are not freed under us because of other operations on the slab that may independently remove the objects.
[This patch is already in mm]
--- include/linux/mm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/mm.h +1 -1
@@ -227,7 +227,7 @@ static inline int put_page_testzero(stru*/ static inline int get_page_unless_zero (struct page *page) { -VM_BUG_ON (PageCompound (page)); +VM_BUG_ON (PageTail (page));return atomic_inc_not_zero (&page->_count); }
PATCH 6/23 SLUB: Extend slabinfo to support -D and -C options
In reply to Christoph Lameter-D lists caches that support defragmentation
-C lists caches that use a ctor.
Change field names for defrag_ratio and remote_node_defrag_ratio.
Add determination of the allocation ratio for a slab. The allocation ratio is the percentage of available slots for objects in use.
--- Documentation/vm/slabinfo.c | 52 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 8 deletions(-)
Documentation/vm/slabinfo.c +44 -8
@@ -31,6 +31,8 @@ struct slabinfo {int hwcache_align, object_size, objs_per_slab;int sanity_checks, slab_size, store_user, trace;int order, poison, reclaim_account, red_zone; +int defrag, ctor; +int defrag_ratio, remote_node_defrag_ratio;unsigned long partial, objects, slabs;int numa[MAX_NODES ];int numa_partial[MAX_NODES ];
@@ -57,6 +59,8 @@ int show_slab = 0;int skip_zero =1 ;int show_numa =0 ;int show_track =0 ; +int show_defrag =0 ; +int show_ctor =0 ;int show_first_alias =0 ;int validate =0 ;int shrink =0 ;
@@ -91,18 +95,20 @@ void fatal(const char *x, ...)void usage (void ) {printf ("slabinfo 5/7/2007. (c) 2007 sgi. [email protected]\n\n" -"slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n" +"slabinfo [-aCDefhilnosSrtTvz1] [-d debugopts] [slab-regexp]\n" "-a|--aliases Show aliases\n" +"-C|--ctor Show slabs with ctors\n" "-d<options>|--debug=<options> Set/Clear Debug options\n" -"-e|--empty Show empty slabs\n" +"-D|--defrag Show defragmentable caches\n" +"-e|--empty Show empty slabs\n" "-f|--first-alias Show first alias\n" "-h|--help Show usage information\n" "-i|--inverted Inverted list\n" "-l|--slabs Show slabs\n" "-n|--numa Show NUMA information\n" -"-o|--ops Show kmem_cache_ops\n" +"-o|--ops Show kmem_cache_ops\n" "-s|--shrink Shrink slabs\n" -"-r|--report Detailed report on single slabs\n" +"-r|--report Detailed report on single slabs\n" "-S|--Size Sort by size\n" "-t|--tracking Show alloc/free information\n" "-T|--Totals Show summary information\n"
@@ -282,7 +288,7 @@ int line = 0;void first_line (void ) {printf ("Name Objects Objsize Space " -"Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n" ); +"Slabs/Part/Cpu O/S O %%Ra %%Ef Flg\n" ); }/*
@@ -325,7 +331,7 @@ void slab_numa(struct slabinfo *s, int mreturn ;if (!line) { -printf ("\n%-21s:" , mode ?"NUMA nodes" :"Slab" ); +printf ("\n%-21s: Rto " , mode ?"NUMA nodes" :"Slab" );for (node =0 ; node <= highest_node; node++)printf (" %4d" , node);printf ("\n----------------------" );
@@ -334,6 +340,7 @@ void slab_numa(struct slabinfo *s, int mprintf ("\n" ); }printf ("%-21s " , mode ?"All slabs" : s->name); +printf ("%3d " , s->remote_node_defrag_ratio);for (node =0 ; node <= highest_node; node++) {char b[20 ];
@@ -407,6 +414,8 @@ void report(struct slabinfo *s)printf ("** Slabs are destroyed via RCU\n" );if (s->reclaim_account)printf ("** Reclaim accounting active\n" ); +if (s->defrag) +printf ("** Defragmentation at %d%%\n" , s->defrag_ratio);printf ("\nSizes (bytes) Slabs Debug Memory\n" );printf ("------------------------------------------------------------------------\n" );
@@ -453,6 +462,12 @@ void slabcache(struct slabinfo *s)if (show_empty && s->slabs)return ; +if (show_defrag && !s->defrag) +return ; + +if (show_ctor && !s->ctor) +return ; +store_size (size_str,slab_size (s));snprintf (dist_str,40 ,"%lu/%lu/%d" , s->slabs, s->partial, s->cpu_slabs);
@@ -463,6 +478,10 @@ void slabcache(struct slabinfo *s) *p++ ='*' ;if (s->cache_dma) *p++ ='d' ; +if (s->defrag) + *p++ ='D' ; +if (s->ctor) + *p++ ='C' ;if (s->hwcache_align) *p++ ='A' ;if (s->poison)
@@ -482,7 +501,7 @@ void slabcache(struct slabinfo *s)printf ("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n" , s->name, s->objects, s->object_size, size_str, dist_str, s->objs_per_slab, s->order, - s->slabs ? (s->partial *100 ) / s->slabs :100 , + s->slabs ? (s->objects *100 ) / (s->slabs * s->objs_per_slab) :100 , s->slabs ? (s->objects * s->object_size *100 ) / (s->slabs * (page_size << s->order)) :100 , flags);
@@ -1074,7 +1093,16 @@ void read_slab_dir(void)free (t); slab->store_user =get_obj ("store_user" ); slab->trace =get_obj ("trace" ); + slab->defrag_ratio =get_obj ("defrag_ratio" ); + slab->remote_node_defrag_ratio = +get_obj ("remote_node_defrag_ratio" );chdir (".." ); +if (read_slab_obj (slab,"ops" )) { +if (strstr (buffer,"ctor :" )) + slab->ctor =1 ; +if (strstr (buffer,"kick :" )) + slab->defrag =1 ; + }if (slab->name[0 ] ==':' ) alias_targets++; slab++;
@@ -1124,7 +1152,9 @@ void output_slabs(void)struct option opts[] = { {"aliases" ,0 ,NULL ,'a' }, + {"ctor" ,0 ,NULL ,'C' }, {"debug" ,2 ,NULL ,'d' }, + {"defrag" ,0 ,NULL ,'D' }, {"empty" ,0 ,NULL ,'e' }, {"first-alias" ,0 ,NULL ,'f' }, {"help" ,0 ,NULL ,'h' },
@@ -1149,7 +1179,7 @@ int main(int argc, char *argv[]) page_size =getpagesize (); -while ((c =getopt_long (argc, argv,"ad::efhil1noprstvzTS" , +while ((c =getopt_long (argc, argv,"ad::efhil1noprstvzCDTS" , opts,NULL )) !=-1 )switch (c) {case '1' :
@@ -1199,6 +1229,12 @@ int main(int argc, char *argv[])case 'z' : skip_zero =0 ;break ; +case 'C' : + show_ctor =1 ; +break ; +case 'D' : + show_defrag =1 ; +break ;case 'T' : show_totals =1 ;break ;
Re: [patch 06/23] SLUB: Extend slabinfo to support -D and -C options
On (06/11/07 17:11), Christoph Lameter didst pronounce:
Quoted 9 lines
(quoted diff) +0
-2-D lists caches that support defragmentation -C lists caches that use a ctor.Change field names for
defrag_ratioandremote_node_defrag_ratio.Add determination of the allocation ratio for a slab. The allocation ratio is the percentage of available slots for objects in use.
Total aside, is there any plan to merge slabinfo or something similar in procps? Alternatively, is having a compatability /proc/slabinfo in the works anywhere? Latest git doesn't appear to have anything on it but I could easily have missed it in -mm or somewhere else.
Quoted 173 lines
Reviewed-by Rik van Riel <[email protected]>Signed-off-by Christoph Lameter <[email protected]>--- Documentation/vm/slabinfo.c | 52 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 8 deletions(-)Index:
linux-2.6.23-mm1/Documentation/vm/slabinfo.c
===================================================================Documentation/vm/slabinfo.c +44
-8@@ -31,6 +31,8 @@ struct slabinfo {int hwcache_align, object_size, objs_per_slab;int sanity_checks, slab_size, store_user, trace;int order, poison, reclaim_account, red_zone; +int defrag, ctor; +int defrag_ratio, remote_node_defrag_ratio;unsigned long partial, objects, slabs;int numa[MAX_NODES ];int numa_partial[MAX_NODES ];@@ -57,6 +59,8 @@ int show_slab = 0;int skip_zero =1 ;int show_numa =0 ;int show_track =0 ; +int show_defrag =0 ; +int show_ctor =0 ;int show_first_alias =0 ;int validate =0 ;int shrink =0 ;@@ -91,18 +95,20 @@ void fatal(const char *x, ...)void usage (void ) {printf ("slabinfo 5/7/2007. (c) 2007 sgi. [email protected]\n\n" -"slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n" +"slabinfo [-aCDefhilnosSrtTvz1] [-d debugopts] [slab-regexp]\n" "-a|--aliases Show aliases\n" +"-C|--ctor Show slabs with ctors\n" "-d<options>|--debug=<options> Set/Clear Debug options\n" -"-e|--empty Show empty slabs\n" +"-D|--defrag Show defragmentable caches\n" +"-e|--empty Show empty slabs\n" "-f|--first-alias Show first alias\n" "-h|--help Show usage information\n" "-i|--inverted Inverted list\n" "-l|--slabs Show slabs\n" "-n|--numa Show NUMA information\n" -"-o|--ops Show kmem_cache_ops\n" +"-o|--ops Show kmem_cache_ops\n" "-s|--shrink Shrink slabs\n" -"-r|--report Detailed report on single slabs\n" +"-r|--report Detailed report on single slabs\n" "-S|--Size Sort by size\n" "-t|--tracking Show alloc/free information\n" "-T|--Totals Show summary information\n"@@ -282,7 +288,7 @@ int line = 0;void first_line (void ) {printf ("Name Objects Objsize Space " -"Slabs/Part/Cpu O/S O %%Fr %%Ef Flg\n" ); +"Slabs/Part/Cpu O/S O %%Ra %%Ef Flg\n" ); }/* @@ -325,7 +331,7 @@ void slab_numa(struct slabinfo *s, int mreturn ;if (!line) { -printf ("\n%-21s:" , mode ?"NUMA nodes" :"Slab" ); +printf ("\n%-21s: Rto " , mode ?"NUMA nodes" :"Slab" );for (node =0 ; node <= highest_node; node++)printf (" %4d" , node);printf ("\n----------------------" );@@ -334,6 +340,7 @@ void slab_numa(struct slabinfo *s, int mprintf ("\n" ); }printf ("%-21s " , mode ?"All slabs" : s->name); +printf ("%3d " , s->remote_node_defrag_ratio);for (node =0 ; node <= highest_node; node++) {char b[20 ];@@ -407,6 +414,8 @@ void report(struct slabinfo *s)printf ("** Slabs are destroyed via RCU\n" );if (s->reclaim_account)printf ("** Reclaim accounting active\n" ); +if (s->defrag) +printf ("** Defragmentation at %d%%\n" , s->defrag_ratio);printf ("\nSizes (bytes) Slabs Debug Memory\n" );printf ("------------------------------------------------------------------------\n" );@@ -453,6 +462,12 @@ void slabcache(struct slabinfo *s)if (show_empty && s->slabs)return ; +if (show_defrag && !s->defrag) +return ; + +if (show_ctor && !s->ctor) +return ; +store_size (size_str,slab_size (s));snprintf (dist_str,40 ,"%lu/%lu/%d" , s->slabs, s->partial, s->cpu_slabs);@@ -463,6 +478,10 @@ void slabcache(struct slabinfo *s) *p++ ='*' ;if (s->cache_dma) *p++ ='d' ; +if (s->defrag) + *p++ ='D' ; +if (s->ctor) + *p++ ='C' ;if (s->hwcache_align) *p++ ='A' ;if (s->poison)@@ -482,7 +501,7 @@ void slabcache(struct slabinfo *s)printf ("%-21s %8ld %7d %8s %14s %4d %1d %3ld %3ld %s\n" , s->name, s->objects, s->object_size, size_str, dist_str, s->objs_per_slab, s->order, - s->slabs ? (s->partial *100 ) / s->slabs :100 , + s->slabs ? (s->objects *100 ) / (s->slabs * s->objs_per_slab) :100 , s->slabs ? (s->objects * s->object_size *100 ) / (s->slabs * (page_size << s->order)) :100 , flags);@@ -1074,7 +1093,16 @@ void read_slab_dir(void)free (t); slab->store_user =get_obj ("store_user" ); slab->trace =get_obj ("trace" ); + slab->defrag_ratio =get_obj ("defrag_ratio" ); + slab->remote_node_defrag_ratio = +get_obj ("remote_node_defrag_ratio" );chdir (".." ); +if (read_slab_obj (slab,"ops" )) { +if (strstr (buffer,"ctor :" )) + slab->ctor =1 ; +if (strstr (buffer,"kick :" )) + slab->defrag =1 ; + }if (slab->name[0 ] ==':' ) alias_targets++; slab++;@@ -1124,7 +1152,9 @@ void output_slabs(void)struct option opts[] = { {"aliases" ,0 ,NULL ,'a' }, + {"ctor" ,0 ,NULL ,'C' }, {"debug" ,2 ,NULL ,'d' }, + {"defrag" ,0 ,NULL ,'D' }, {"empty" ,0 ,NULL ,'e' }, {"first-alias" ,0 ,NULL ,'f' }, {"help" ,0 ,NULL ,'h' },@@ -1149,7 +1179,7 @@ int main(int argc, char *argv[]) page_size =getpagesize (); -while ((c =getopt_long (argc, argv,"ad::efhil1noprstvzTS" , +while ((c =getopt_long (argc, argv,"ad::efhil1noprstvzCDTS" , opts,NULL )) !=-1 )switch (c) {case '1' :@@ -1199,6 +1229,12 @@ int main(int argc, char *argv[])case 'z' : skip_zero =0 ;break ; +case 'C' : + show_ctor =1 ; +break ; +case 'D' : + show_defrag =1 ; +break ;case 'T' : show_totals =1 ;break ;Signature · 1 line
--
Signature · 10 lines
-- Mel Gorman Part-time Phd Student Linux Technology Center University of Limerick IBM Dublin Software Lab -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 7/23 SLUB: Add defrag_ratio field and sysfs support.
In reply to Christoph LameterThe defrag_ratio is used to set the threshold at which defragmentation should be run on a slabcache.
The allocation ratio is measured in a percentage of the available slots. The percentage will be lower for slabs that are more fragmented.
Add a defrag ratio field and set it to 30% by default. A limit of 30% specified that less than 3 out of 10 available slots for objects are in use before reclaim occurs.
--- include/linux/slub_def.h | 7 +++++++ mm/slub.c | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+)
include/linux/slub_def.h +7 -0
@@ -53,6 +53,13 @@ struct kmem_cache {void (*ctor)(struct kmem_cache *,void *);int inuse;/* Offset to metadata */ int align;/* Alignment */ +int defrag_ratio;/* +* objects/possible-objects limit. If we have +* less that the specified percentage of +* objects allocated then defrag passes +* will start to occur during reclaim. +*/ +const char *name;/* Name (only for display!) */ struct list_head list;/* List of slab caches */ #ifdef CONFIG_SLUB_DEBUG
mm/slub.c +18 -0
@@ -2363,6 +2363,7 @@ static int kmem_cache_open(struct kmem_c goto error; s->refcount =1 ; + s->defrag_ratio =30 ;#ifdef CONFIG_NUMA s->remote_node_defrag_ratio =100 ;#endif
@@ -4005,6 +4006,22 @@ static ssize_t free_calls_show(struct km }SLAB_ATTR_RO (free_calls); +static ssize_t defrag_ratio_show (struct kmem_cache *s,char *buf) +{ +return sprintf (buf,"%d\n" , s->defrag_ratio); +} + +static ssize_t defrag_ratio_store (struct kmem_cache *s, +const char *buf,size_t length) +{ +int n =simple_strtoul (buf,NULL ,10 ); + +if (n <100 ) + s->defrag_ratio = n; +return length; +} +SLAB_ATTR (defrag_ratio); +#ifdef CONFIG_NUMA static ssize_t remote_node_defrag_ratio_show (struct kmem_cache *s,char *buf) {
@@ -4047,6 +4064,7 @@ static struct attribute * slab_attrs[] = &shrink_attr.attr, &alloc_calls_attr.attr, &free_calls_attr.attr, + &defrag_ratio_attr.attr, #ifdef CONFIG_ZONE_DMA &cache_dma_attr.attr, #endif
Re: [patch 07/23] SLUB: Add defrag_ratio field and sysfs support.
Hi Christoph,
include/linux/slub_def.h struct kmem_cache { · line 58
Quoted 9 lines · Christoph Lameter
include/linux/slub_def.h +3
-0@@ -53,6 +53,13 @@ struct kmem_cache {void (*ctor)(struct kmem_cache *,void *);int inuse;/* Offset to metadata */ int align;/* Alignment */ +int defrag_ratio;/* +* objects/possible-objects limit. If we have +* less that the specified percentage of
That should be `less than', I guess.
Hannes
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 07/23] SLUB: Add defrag_ratio field and sysfs support.
Quoted 14 lines · Johannes Weiner
Hi Christoph,
include/linux/slub_def.h struct kmem_cache { · line 58
Quoted 9 lines · Christoph Lameter
include/linux/slub_def.h +3
-0@@ -53,6 +53,13 @@ struct kmem_cache {void (*ctor)(struct kmem_cache *,void *);int inuse;/* Offset to metadata */ int align;/* Alignment */ +int defrag_ratio;/* +* objects/possible-objects limit. If we have +* less that the specified percentage of That should be `less than', I guess.
Correct.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 07/23] SLUB: Add defrag_ratio field and sysfs support.
In reply to Christoph LameterOn (06/11/07 17:11), Christoph Lameter didst pronounce:
Quoted 3 lines
The
defrag_ratiois used to set the threshold at which defragmentation should be run on a slabcache.
I'm thick, I would like to see a quick note here on what defragmentation means. Also, this defrag_ratio seems to have a significantly different meaning to the other defrag_ratio which isn't helping my poor head at all.
"The defrag_ratio sets a threshold at which a slab will be vacated of all it's objects and the pages freed during memory reclaim."
?
Quoted 78 lines
The allocation ratio is measured in a percentage of the available slots. The percentage will be lower for slabs that are more fragmented.
Add a defrag ratio field and set it to 30% by default. A limit of 30% specified that less than 3 out of 10 available slots for objects are in use before reclaim occurs.
Reviewed-by Rik van Riel <[email protected]>Signed-off-by Christoph Lameter <[email protected]>--- include/linux/slub_def.h | 7 +++++++ mm/slub.c | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+)Index:
linux-2.6/include/linux/slub_def.h
===================================================================include/linux/slub_def.h +7
-0@@ -53,6 +53,13 @@ struct kmem_cache {void (*ctor)(struct kmem_cache *,void *);int inuse;/* Offset to metadata */ int align;/* Alignment */ +int defrag_ratio;/* +* objects/possible-objects limit. If we have +* less that the specified percentage of +* objects allocated then defrag passes +* will start to occur during reclaim. +*/ +const char *name;/* Name (only for display!) */ struct list_head list;/* List of slab caches */ #ifdef CONFIG_SLUB_DEBUG Index:
linux-2.6/mm/slub.c
===================================================================mm/slub.c +18
-0@@ -2363,6 +2363,7 @@ static int kmem_cache_open(struct kmem_c goto error; s->refcount =1 ; + s->defrag_ratio =30 ;#ifdef CONFIG_NUMA s->remote_node_defrag_ratio =100 ;#endif @@ -4005,6 +4006,22 @@ static ssize_t free_calls_show(struct km }SLAB_ATTR_RO (free_calls); +static ssize_t defrag_ratio_show (struct kmem_cache *s,char *buf) +{ +return sprintf (buf,"%d\n" , s->defrag_ratio); +} + +static ssize_t defrag_ratio_store (struct kmem_cache *s, +const char *buf,size_t length) +{ +int n =simple_strtoul (buf,NULL ,10 ); + +if (n <100 ) + s->defrag_ratio = n; +return length; +} +SLAB_ATTR (defrag_ratio); +#ifdef CONFIG_NUMA static ssize_t remote_node_defrag_ratio_show (struct kmem_cache *s,char *buf) {@@ -4047,6 +4064,7 @@ static struct attribute * slab_attrs[] = &shrink_attr.attr, &alloc_calls_attr.attr, &free_calls_attr.attr, + &defrag_ratio_attr.attr, #ifdef CONFIG_ZONE_DMA &cache_dma_attr.attr, #endifSignature · 1 line
--
Signature · 10 lines
-- Mel Gorman Part-time Phd Student Linux Technology Center University of Limerick IBM Dublin Software Lab -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 07/23] SLUB: Add defrag_ratio field and sysfs support.
Quoted 9 lines · Mel Gorman
On (06/11/07 17:11), Christoph Lameter didst pronounce:
Quoted 3 lines
The
defrag_ratiois used to set the threshold at which defragmentation should be run on a slabcache.I'm thick, I would like to see a quick note here on what defragmentation means. Also, this
defrag_ratioseems to have a significantly different meaning to the otherdefrag_ratiowhich isn't helping my poor head at all.
Yes that is why they have different names. The remote_node_defrag ratio controls the amount of remote allocs we do to reduce fragmentation.
Quoted 2 lines
"The
defrag_ratiosets a threshold at which a slab will be vacated of all it's objects and the pages freed during memory reclaim."
Sortof. If a slab is beyond the threshold during reclaim then reclaim will attempt to free the remaining objects in the slab to reclaim the whole slab.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 8/23 SLUB: Replace ctor field with ops field in /sys/slab/:0000008 /sys/slab/:0000016 /sys/slab/:0000024 /sys/slab/:0000032 /sys/slab/:0000040 /sys/slab/:0000048 /sys/slab/:0000056 /sys/slab/:0000064 /sys/slab/:0000072 /sys/slab/:0000080 /sys/slab/:0000088 /sys/slab/:0000096 /sys/slab/:0000104 /sys/slab/:0000128 /sys/slab/:0000144 /sys/slab/:0000184 /sys/slab/:0000192 /sys/slab/:0000216 /sys/slab/:0000256 /sys/slab/:0000344 /sys/slab/:0000384 /sys/slab/:0000448 /sys/slab/:0000512 /sys/slab/:0000768 /sys/slab/:0000968 /sys/slab/:0001024 /sys/slab/:0001152 /sys/slab/:0001312 /sys/slab/:0001536 /sys/slab/:0002048 /sys/slab/:0003072 /sys/slab/:0004096 /sys/slab/:a-0000016 /sys/slab/:a-0000024 /sys/slab/:a-0000056 /sys/slab/:a-0000080 /sys/slab/:a-0000128 /sys/slab/Acpi-Namespace /sys/slab/Acpi-Operand /sys/slab/Acpi-Parse /sys/slab/Acpi-ParseExt /sys/slab/Acpi-State /sys/slab/RAW /sys/slab/TCP /sys/slab/UDP /sys/slab/UDP-Lite /sys/slab/UNIX /sys/slab/anon_vma /s ys/slab/arp_cache /sys/slab/bdev_cache /sys/slab/bio /sys/slab/biovec-1 /sys/slab/biovec-128 /sys/slab/biovec-16 /sys/slab/biovec-256 /sys/slab/biovec-4 /sys/slab/biovec-64 /sys/slab/blkdev_ioc /sys/slab/blkdev_queue /sys/slab/blkdev_requests /sys/slab/buffer_head /sys/slab/cfq_io_context /sys/slab/cfq_queue /sys/slab/dentry /sys/slab/eventpoll_epi /sys/slab/eventpoll_pwq /sys/slab/ext2_inode_cache /sys/slab/ext3_inode_cache /sys/slab/fasync_cache /sys/slab/file_lock_cache /sys/slab/files_cache /sys/slab/filp /sys/slab/flow_cache /sys/slab/fs_cache /sys/slab/idr_layer_cache /sys/slab/inet_peer_cache /sys/slab/inode_cache /sys/slab/inotify_event_cache /sys/slab/inotify_watch_cache /sys/slab/ip_dst_cache /sys/slab/ip_fib_alias /sys/slab/ip_fib_hash /sys/slab/jbd_1k /sys/slab/jbd_4k /sys/slab/journal_handle /sys/slab/journal_head /sys/slab/kiocb /sys/slab/kioctx /sys/slab/kmalloc-1024 /sys/slab/kmalloc-128 /sys/slab/kmalloc-16 /sys/slab/kmalloc-192 /sys/slab/kmalloc-2048 /sys/s lab/kmalloc-256 /sys/slab/kmalloc-32 /sys/slab/kmalloc-512 /sys/slab/kmalloc-64 /sys/slab/kmalloc-8 /sys/slab/kmalloc-96 /sys/slab/mm_struct /sys/slab/mnt_cache /sys/slab/mqueue_inode_cache /sys/slab/names_cache /sys/slab/net_namespace /sys/slab/nfs_direct_cache /sys/slab/nfs_inode_cache /sys/slab/nfs_page /sys/slab/nfs_read_data /sys/slab/nfs_write_data /sys/slab/nfsd4_delegations /sys/slab/nfsd4_files /sys/slab/nfsd4_stateids /sys/slab/nfsd4_stateowners /sys/slab/nsproxy /sys/slab/pid /sys/slab/posix_timers_cache /sys/slab/proc_inode_cache /sys/slab/radix_tree_node /sys/slab/request_sock_TCP /sys/slab/revoke_record /sys/slab/revoke_table /sys/slab/rpc_buffers /sys/slab/rpc_inode_cache /sys/slab/rpc_tasks /sys/slab/scsi_cmd_cache /sys/slab/scsi_io_context /sys/slab/secpath_cache /sys/slab/sgpool-128 /sys/slab/sgpool-16 /sys/slab/sgpool-32 /sys/slab/sgpool-64 /sys/slab/sgpool-8 /sys/slab/shmem_inode_cache /sys/slab/sighand_cache /sys/slab/signal_cache /sys/slab/sigqueue /sys /slab/skbuff_fclone_cache /sys/slab/skbuff_head_cache /sys/slab/sock_inode_cache /sys/slab/sysfs_dir_cache /sys/slab/task_struct /sys/slab/tcp_bind_bucket /sys/slab/tw_sock_TCP /sys/slab/uhci_urb_priv /sys/slab/uid_cache /sys/slab/vm_area_struct /sys/slab/xfrm_dst_cache
In reply to Christoph LameterCreate an ops field in /sys/slab/*/ops to contain all the operations defined on a slab. This will be used to display the additional operations that will be defined soon.
--- mm/slub.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
mm/slub.c +9 -7
@@ -3789,16 +3789,18 @@ static ssize_t order_show(struct kmem_ca }SLAB_ATTR_RO (order); -static ssize_t ctor_show (struct kmem_cache *s,char *buf) +static ssize_t ops_show (struct kmem_cache *s,char *buf) { -if (s->ctor) { -int n =sprint_symbol (buf, (unsigned long )s->ctor); +int x =0 ; -return n +sprintf (buf + n,"\n" ); +if (s->ctor) { + x +=sprintf (buf + x,"ctor : " ); + x +=sprint_symbol (buf + x, (unsigned long )s->ops->ctor); + x +=sprintf (buf + x,"\n" ); } -return 0 ; +return x; } -SLAB_ATTR_RO (ctor); +SLAB_ATTR_RO (ops);static ssize_t aliases_show (struct kmem_cache *s,char *buf) {
@@ -4049,7 +4051,7 @@ static struct attribute * slab_attrs[] = &slabs_attr.attr, &partial_attr.attr, &cpu_slabs_attr.attr, - &ctor_attr.attr, + &ops_attr.attr, &aliases_attr.attr, &align_attr.attr, &sanity_checks_attr.attr,
PATCH 9/23 SLUB: Add get() and kick() methods
In reply to Christoph LameterAdd the two methods needed for defragmentation and add the display of the methods via the proc interface.
Add documentation explaining the use of these methods.
--- include/linux/slab.h | 3 +++ include/linux/slub_def.h | 31 +++++++++++++++++++++++++++++++ mm/slub.c | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 2 deletions(-)
include/linux/slab.h +3 -0
@@ -56,6 +56,9 @@ struct kmem_cache *kmem_cache_create(con void (*)(struct kmem_cache *, void *));void kmem_cache_destroy (struct kmem_cache *);int kmem_cache_shrink (struct kmem_cache *); +void kmem_cache_setup_defrag (struct kmem_cache *s, +void *(*get)(struct kmem_cache *,int nr,void **), +void (*kick)(struct kmem_cache *,int nr,void **,void *private));void kmem_cache_free (struct kmem_cache *,void *);unsigned int kmem_cache_size (struct kmem_cache *);const char *kmem_cache_name (struct kmem_cache *);
include/linux/slub_def.h +31 -0
@@ -51,6 +51,37 @@ struct kmem_cache {int objects;/* Number of objects in slab */ int refcount;/* Refcount for slab cache destroy */ void (*ctor)(struct kmem_cache *,void *); +/* +* Called with slab lock held and interrupts disabled. +* No slab operation may be performed in get(). +* +* Parameters passed are the number of objects to process +* and an array of pointers to objects for which we +* need references. +* +* Returns a pointer that is passed to the kick function. +* If all objects cannot be moved then the pointer may +* indicate that this wont work and then kick can simply +* remove the references that were already obtained. +* +* The array passed to get() is also passed to kick(). The +* function may remove objects by setting array elements to NULL. +*/ +void *(*get)(struct kmem_cache *,int nr,void **); + +/* +* Called with no locks held and interrupts enabled. +* Any operation may be performed in kick(). +* +* Parameters passed are the number of objects in the array, +* the array of pointers to the objects and the pointer +* returned by get(). +* +* Success is checked by examining the number of remaining +* objects in the slab. +*/ +void (*kick)(struct kmem_cache *,int nr,void **,void *private); +int inuse;/* Offset to metadata */ int align;/* Alignment */ int defrag_ratio;/*
mm/slub.c +30 -2
@@ -2760,6 +2760,20 @@ void kfree(const void *x) }EXPORT_SYMBOL (kfree); +void kmem_cache_setup_defrag (struct kmem_cache *s, +void *(*get)(struct kmem_cache *,int nr,void **), +void (*kick)(struct kmem_cache *,int nr,void **,void *private)) +{ +/* +* Defragmentable slabs must have a ctor otherwise objects may be +* in an undetermined state after they are allocated. +*/ +BUG_ON (!s->ctor); + s->get = get; + s->kick = kick; +} +EXPORT_SYMBOL (kmem_cache_setup_defrag); +static unsigned long count_partial (struct kmem_cache_node *n) {unsigned long flags;
@@ -3058,7 +3072,7 @@ static int slab_unmergeable(struct kmem_if (slub_nomerge || (s->flags &SLUB_NEVER_MERGE ))return 1 ; -if (s->ctor) +if (s->ctor || s->kick || s->get)return 1 ;/*
@@ -3795,7 +3809,21 @@ static ssize_t ops_show(struct kmem_cachif (s->ctor) { x +=sprintf (buf + x,"ctor : " ); - x +=sprint_symbol (buf + x, (unsigned long )s->ops->ctor); + x +=sprint_symbol (buf + x, (unsigned long )s->ctor); + x +=sprintf (buf + x,"\n" ); + } + +if (s->get) { + x +=sprintf (buf + x,"get : " ); + x +=sprint_symbol (buf + x, + (unsigned long )s->get); + x +=sprintf (buf + x,"\n" ); + } + +if (s->kick) { + x +=sprintf (buf + x,"kick : " ); + x +=sprint_symbol (buf + x, + (unsigned long )s->kick); x +=sprintf (buf + x,"\n" ); }return x;
Re: [patch 09/23] SLUB: Add get() and kick() methods
Quoted 18 lines · Christoph Lameter
Add the two methods needed for defragmentation and add the display of the methods via the proc interface.
Add documentation explaining the use of these methods.
Reviewed-by Rik van Riel <[email protected]>Signed-off-by Christoph Lameter <[email protected]>--- include/linux/slab.h | 3 +++ include/linux/slub_def.h | 31 +++++++++++++++++++++++++++++++ mm/slub.c | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 2 deletions(-)Index:
linux-2.6/include/linux/slab.h
===================================================================
include/linux/slab.h struct kmem_cache *kmem_cache_create(con · line 64
Quoted 10 lines
include/linux/slab.h +3
-0@@ -56,6 +56,9 @@ struct kmem_cache *kmem_cache_create(con void (*)(struct kmem_cache *, void *));void kmem_cache_destroy (struct kmem_cache *);int kmem_cache_shrink (struct kmem_cache *); +void kmem_cache_setup_defrag (struct kmem_cache *s, +void *(*get)(struct kmem_cache *,int nr,void **), +void (*kick)(struct kmem_cache *,int nr,void **,void *private));void kmem_cache_free (struct kmem_cache *,void *);unsigned int kmem_cache_size (struct kmem_cache *);const char *kmem_cache_name (struct kmem_cache *);
A static inline dummy function for CONFIG_SLUB=n seems to be missing?
cu
Adrian
Signature · 10 lines
"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon Seed
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>Re: [patch 09/23] SLUB: Add get() and kick() methods
Quoted 1 line · Adrian Bunk
A static inline dummy function for
CONFIG_SLUB=nseems to be missing?
Correct. This patch is needed so that building with SLAB will work.
Slab defrag: Provide empty kmem_cache_setup_defrag function for SLAB.
Provide an empty function to satisfy dependencies for Slab defrag.
--- mm/slab.c | 7 +++++++ 1 file changed, 7 insertions(+)
mm/slab.c +7 -0
@@ -2535,6 +2535,13 @@ static int __cache_shrink(struct kmem_careturn (ret ?1 :0 ); } +void kmem_cache_setup_defrag (struct kmem_cache *s, +void *(*get)(struct kmem_cache *,int nr,void **), +void (*kick)(struct kmem_cache *,int nr,void **,void *private)) +{ +} +EXPORT_SYMBOL (kmem_cache_setup_defrag); +/** * kmem_cache_shrink - Shrink a cache. * @cachep: The cache to shrink.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 09/23] SLUB: Add get() and kick() methods
Quoted 21 lines · Christoph Lameter
Quoted 1 line · Adrian Bunk
A static inline dummy function for
CONFIG_SLUB=nseems to be missing?Correct. This patch is needed so that building with SLAB will work.
Slab defrag: Provide empty
kmem_cache_setup_defragfunction for SLAB.Provide an empty function to satisfy dependencies for Slab defrag.
Signed-off-by Christoph Lameter <[email protected]>?--- mm/slab.c | 7 +++++++ 1 file changed, 7 insertions(+)Index:
linux-2.6/mm/slab.c
===================================================================
mm/slab.c static int __cache_shrink(struct kmem_ca · line 2544
Quoted 10 lines
mm/slab.c +7
-0@@ -2535,6 +2535,13 @@ static int __cache_shrink(struct kmem_careturn (ret ?1 :0 ); } +void kmem_cache_setup_defrag (struct kmem_cache *s, +void *(*get)(struct kmem_cache *,int nr,void **), +void (*kick)(struct kmem_cache *,int nr,void **,void *private)) +{ +} +EXPORT_SYMBOL (kmem_cache_setup_defrag); +
- this misses slob
- this wastes memory
An empty static inline function in slab.h would be better.
cu
Adrian
Signature · 10 lines
"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon Seed
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>PATCH 10/23 SLUB: Sort slab cache list and establish maximum objects for defrag slabs
In reply to Christoph LameterWhen defragmenting slabs then it is advantageous to have all defragmentable slabs together at the beginning of the list so that we do not have to scan the complete list. When adding a slab cache put defragmentable caches first and others last.
Determine the maximum number of objects in defragmentable slabs. This allows to size the allocation of arrays holding refs to these objects later.
--- mm/slub.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
mm/slub.c +17 -2
@@ -198,6 +198,9 @@ static enum {static DECLARE_RWSEM (slub_lock);static LIST_HEAD (slab_caches); +/* Maximum objects in defragmentable slabs */ +static unsigned int max_defrag_slab_objects =0 ; +/* * Tracking user of a slab. */
@@ -2546,7 +2549,7 @@ static struct kmem_cache *create_kmalloc flags, NULL)) goto panic; -list_add (&s->list, &slab_caches); +list_add_tail (&s->list, &slab_caches);up_write (&slub_lock);if (sysfs_slab_add (s)) goto panic;
@@ -2760,6 +2763,13 @@ void kfree(const void *x) }EXPORT_SYMBOL (kfree); +static inline void *alloc_scratch (void ) +{ +return kmalloc (max_defrag_slab_objects *sizeof (void *) + +BITS_TO_LONGS (max_defrag_slab_objects) *sizeof (unsigned long ), +GFP_KERNEL ); +} +void kmem_cache_setup_defrag (struct kmem_cache *s,void *(*get)(struct kmem_cache *,int nr,void **),void (*kick)(struct kmem_cache *,int nr,void **,void *private))
@@ -2771,6 +2781,11 @@ void kmem_cache_setup_defrag(struct kmemBUG_ON (!s->ctor); s->get = get; s->kick = kick; +down_write (&slub_lock); +list_move (&s->list, &slab_caches); +if (s->objects > max_defrag_slab_objects) + max_defrag_slab_objects = s->objects; +up_write (&slub_lock); }EXPORT_SYMBOL (kmem_cache_setup_defrag);
@@ -3159,7 +3174,7 @@ struct kmem_cache *kmem_cache_create(conif (s) {if (kmem_cache_open (s,GFP_KERNEL , name, size, align, flags, ctor)) { -list_add (&s->list, &slab_caches); +list_add_tail (&s->list, &slab_caches);up_write (&slub_lock);if (sysfs_slab_add (s)) goto err;
PATCH 11/23 SLUB: Slab defrag core
In reply to Christoph LameterSlab defragmentation (aside from Lumpy Reclaim) may occur:
1. Unconditionally when kmem_cache_shrink is called on a slab cache by the kernel calling kmem_cache_shrink.
2. Use of the slabinfo command line to trigger slab shrinking.
3. Per node defrag conditionally when kmem_cache_defrag(<node>) is called.
Defragmentation is only performed if the fragmentation of the slab is lower than the specified percentage. Fragmentation ratios are measured by calculating the percentage of objects in use compared to the total number of objects that the slab cache could hold.
kmem_cache_defrag takes a node parameter. This can either be -1 if defragmentation should be performed on all nodes, or a node number. If a node number was specified then defragmentation is only performed on a specific node.
Slab defragmentation is a memory intensive operation that can be sped up in a NUMA system if mostly node local memory is accessed. That is the case if we run shrinking on a node after just having run shrink_slabs() reclaim on a node.
A couple of functions must be setup via a call to kmem_cache_setup_defrag() in order for a slabcache to support defragmentation. These are
void *get(struct kmem_cache *s, int nr, void **objects)
Must obtain a reference to the listed objects. SLUB guarantees that the objects are still allocated. However, other threads may be blocked in slab_free() attempting to free objects in the slab. These may succeed as soon as get() returns to the slab allocator. The function must be able to detect such situations and void the attempts to free such objects (by for example voiding the corresponding entry in the objects array).
No slab operations may be performed in get(). Interrupts are disabled. What can be done is very limited. The slab lock for the page that contains the object is taken. Any attempt to perform a slab operation may lead to a deadlock.
get() returns a private pointer that is passed to kick. Should we be unable to obtain all references then that pointer may indicate to the kick() function that it should not attempt any object removal or move but simply remove the reference counts.
void kick(struct kmem_cache *, int nr, void **objects, void *get_result)
After SLUB has established references to the objects in a slab it will then drop all locks and use kick() to move objects out of the slab. The existence of the object is guaranteed by virtue of the earlier obtained references via get(). The callback may perform any slab operation since no locks are held at the time of call.
The callback should remove the object from the slab in some way. This may be accomplished by reclaiming the object and then running kmem_cache_free() or reallocating it and then running kmem_cache_free(). Reallocation is advantageous because the partial slabs were just sorted to have the partial slabs with the most objects first. Reallocation is likely to result in filling up a slab in addition to freeing up one slab. A filled up slab can also be removed from the partial list. So there could be a double effect.
Kick() does not return a result. SLUB will check the number of remaining objects in the slab. If all objects were removed then we know that the operation was successful.
--- mm/slab.c | 5 + mm/slub.c | 275 ++++++++++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 222 insertions(+), 58 deletions(-)
mm/slab.c +5 -0
@@ -2554,6 +2554,11 @@ int kmem_cache_shrink(struct kmem_cache }EXPORT_SYMBOL (kmem_cache_shrink); +int kmem_cache_defrag (int node) +{ +return 0 ; +} +/** * kmem_cache_destroy - delete a cache * @cachep: the cache to destroy
mm/slub.c +217 -58
307 lines not on this page · raw message
Re: [patch 11/23] SLUB: Slab defrag core
This was so far only in the slab defrag git tree.
PATCH 12/23 SLUB: Trigger defragmentation from memory reclaim
In reply to Christoph LameterThis patch triggers slab defragmentation from memory reclaim. The logical point for this is after slab shrinking was performed in vmscan.c. At that point the fragmentation ratio of a slab was increased because objects were freed via the LRUs. So we call kmem_cache_defrag from there.
slab_shrink() from vmscan.c is called in some contexts to do global shrinking of slabs and in others to do shrinking for a particular zone. Pass the zone to slab_shrink, so that slab_shrink can call kmem_cache_defrag() and restrict the defragmentation to the node that is under memory pressure.
--- fs/drop_caches.c | 2 +- include/linux/mm.h | 2 +- include/linux/slab.h | 1 + mm/vmscan.c | 26 +++++++++++++++++++------- 4 files changed, 22 insertions(+), 9 deletions(-)
fs/drop_caches.c +1 -1
@@ -50,7 +50,7 @@ void drop_slab(void)int nr_objects;do { - nr_objects =shrink_slab (1000 ,GFP_KERNEL ,1000 ); + nr_objects =shrink_slab (1000 ,GFP_KERNEL ,1000 ,NULL ); }while (nr_objects >10 ); }
include/linux/mm.h +1 -1
@@ -1118,7 +1118,7 @@ int in_gate_area_no_task(unsigned long aint drop_caches_sysctl_handler (struct ctl_table *,int ,struct file *,void __user *,size_t *,loff_t *);unsigned long shrink_slab (unsigned long scanned,gfp_t gfp_mask, -unsigned long lru_pages); +unsigned long lru_pages,struct zone *z);void drop_pagecache (void );void drop_slab (void );
include/linux/slab.h +1 -0
@@ -63,6 +63,7 @@ void kmem_cache_free(struct kmem_cache *unsigned int kmem_cache_size (struct kmem_cache *);const char *kmem_cache_name (struct kmem_cache *);int kmem_ptr_validate (struct kmem_cache *cachep,const void *ptr); +int kmem_cache_defrag (int node);/* * Please use this macro to create slab caches. Simply specify the
mm/vmscan.c +19 -7
@@ -150,10 +150,18 @@ EXPORT_SYMBOL(unregister_shrinker);* are eligible for the caller's allocation attempt. It is used for balancing * slab reclaim versus page reclaim. * +* zone is the zone for which we are shrinking the slabs. If the intent +* is to do a global shrink then zone may be NULL. Specification of a +* zone is currently only used to limit slab defragmentation to a NUMA node. +* The performace of shrink_slab would be better (in particular under NUMA) +* if it could be targeted as a whole to the zone that is under memory +* pressure but the VFS infrastructure does not allow that at the present +* time. +* * Returns the number of slab objects which we shrunk. */ unsigned long shrink_slab (unsigned long scanned,gfp_t gfp_mask, -unsigned long lru_pages) +unsigned long lru_pages,struct zone *zone) {struct shrinker *shrinker;unsigned long ret =0 ;
@@ -210,6 +218,8 @@ unsigned long shrink_slab(unsigned long shrinker->nr += total_scan; }up_read (&shrinker_rwsem); +if (gfp_mask & __GFP_FS) +kmem_cache_defrag (zone ?zone_to_nid (zone) :-1 );return ret; }
@@ -1241,7 +1251,7 @@ unsigned long try_to_free_pages(struct zif (!priority)disable_swap_token (); nr_reclaimed +=shrink_zones (priority, zones, &sc); -shrink_slab (sc.nr_scanned, gfp_mask, lru_pages); +shrink_slab (sc.nr_scanned, gfp_mask, lru_pages,NULL );if (reclaim_state) { nr_reclaimed += reclaim_state->reclaimed_slab; reclaim_state->reclaimed_slab =0 ;
@@ -1419,7 +1429,7 @@ loop_again: nr_reclaimed +=shrink_zone (priority, zone, &sc); reclaim_state->reclaimed_slab =0 ; nr_slab =shrink_slab (sc.nr_scanned,GFP_KERNEL , - lru_pages); + lru_pages, zone); nr_reclaimed += reclaim_state->reclaimed_slab; total_scanned += sc.nr_scanned;if (zone_is_all_unreclaimable (zone))
@@ -1658,7 +1668,7 @@ unsigned long shrink_all_memory(unsigned/* If slab caches are huge, it's better to hit them first */ while (nr_slab >= lru_pages) { reclaim_state.reclaimed_slab =0 ; -shrink_slab (nr_pages, sc.gfp_mask, lru_pages); +shrink_slab (nr_pages, sc.gfp_mask, lru_pages,NULL );if (!reclaim_state.reclaimed_slab)break ;
@@ -1696,7 +1706,7 @@ unsigned long shrink_all_memory(unsigned reclaim_state.reclaimed_slab =0 ;shrink_slab (sc.nr_scanned, sc.gfp_mask, -count_lru_pages ()); +count_lru_pages (),NULL ); ret += reclaim_state.reclaimed_slab;if (ret >= nr_pages) goto out;
@@ -1713,7 +1723,8 @@ unsigned long shrink_all_memory(unsignedif (!ret) {do { reclaim_state.reclaimed_slab =0 ; -shrink_slab (nr_pages, sc.gfp_mask,count_lru_pages ()); +shrink_slab (nr_pages, sc.gfp_mask, +count_lru_pages (),NULL ); ret += reclaim_state.reclaimed_slab; }while (ret < nr_pages && reclaim_state.reclaimed_slab >0 ); }
@@ -1875,7 +1886,8 @@ static int __zone_reclaim(struct zone *z* Note that shrink_slab will free memory on all zones and may * take a long time. */ -while (shrink_slab (sc.nr_scanned, gfp_mask, order) && +while (shrink_slab (sc.nr_scanned, gfp_mask, order, + zone) &&zone_page_state (zone,NR_SLAB_RECLAIMABLE ) > slab_reclaimable - nr_pages) ;
Re: [patch 12/23] SLUB: Trigger defragmentation from memory reclaim
Hi Christoph,
include/linux/slab.h void kmem_cache_free(struct kmem_cache * · line 66
Quoted 9 lines · Christoph Lameter
Index:
linux-2.6/include/linux/slab.h
===================================================================include/linux/slab.h +1
-0@@ -63,6 +63,7 @@ void kmem_cache_free(struct kmem_cache *unsigned int kmem_cache_size (struct kmem_cache *);const char *kmem_cache_name (struct kmem_cache *);int kmem_ptr_validate (struct kmem_cache *cachep,const void *ptr); +int kmem_cache_defrag (int node);
The definition in slab.c always returns 0. Wouldn't a static inline function in the header be better?
include/linux/slab.h void kmem_cache_free(struct kmem_cache * · line 67
Quoted 1 line
include/linux/slab.h +0
-0* Returns the number of slab objects which we shrunk.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Quoted 8 lines
include/linux/slab.h +1
-1*/ unsigned long shrink_slab (unsigned long scanned,gfp_t gfp_mask, -unsigned long lru_pages) +unsigned long lru_pages,struct zone *zone) {struct shrinker *shrinker;unsigned long ret =0 ;
include/linux/slab.h unsigned long shrink_slab(unsigned long · line 224
Quoted 7 lines
include/linux/slab.h +2
-0@@ -210,6 +218,8 @@ unsigned long shrink_slab(unsigned long shrinker->nr += total_scan; }up_read (&shrinker_rwsem); +if (gfp_mask & __GFP_FS) +kmem_cache_defrag (zone ?zone_to_nid (zone) :-1 );return ret; }
What about the objects that kmem_cache_defrag() releases? Shouldn't they be counted too?
ret += kmem_cache_defrag(...)
Or am I overseeing something here?
Hannes
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 12/23] SLUB: Trigger defragmentation from memory reclaim
Quoted 12 lines · Johannes Weiner
mm/vmscan.c unsigned long shrink_slab(unsigned long · line 224
Quoted 8 lines
mm/vmscan.c +2
-0@@ -210,6 +218,8 @@ unsigned long shrink_slab(unsigned long shrinker->nr += total_scan; }up_read (&shrinker_rwsem); +if (gfp_mask & __GFP_FS) +kmem_cache_defrag (zone ?zone_to_nid (zone) :-1 );return ret; }What about the objects that
kmem_cache_defrag()releases? Shouldn't they be counted too?
Quoted 3 lines
ret += kmem_cache_defrag(...)Or am I overseeing something here?
kmem_cache_defrag returns the number of pages that were released by defrag actions.
shrink_slab returns the number of objects released by the shrinkers. kmem_cache_defrag has no way of knowing how many objects where released by the kick methods. The kick method may have chosen to reallocate the object.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 12/23] SLUB: Trigger defragmentation from memory reclaim
In reply to Christoph LameterOn (06/11/07 17:11), Christoph Lameter didst pronounce:
Quoted 84 lines
This patch triggers slab defragmentation from memory reclaim. The logical point for this is after slab shrinking was performed in
vmscan.c. At that point the fragmentation ratio of a slab was increased because objects were freed via the LRUs. So we callkmem_cache_defragfrom there.
slab_shrink()fromvmscan.cis called in some contexts to do global shrinking of slabs and in others to do shrinking for a particular zone. Pass the zone toslab_shrink, so thatslab_shrinkcan callkmem_cache_defrag()and restrict the defragmentation to the node that is under memory pressure.Reviewed-by Rik van Riel <[email protected]>Signed-off-by Christoph Lameter <[email protected]>--- fs/drop_caches.c | 2 +- include/linux/mm.h | 2 +- include/linux/slab.h | 1 + mm/vmscan.c | 26 +++++++++++++++++++------- 4 files changed, 22 insertions(+), 9 deletions(-)Index:
linux-2.6/fs/drop_caches.c
===================================================================fs/drop_caches.c +1
-1@@ -50,7 +50,7 @@ void drop_slab(void)int nr_objects;do { - nr_objects =shrink_slab (1000 ,GFP_KERNEL ,1000 ); + nr_objects =shrink_slab (1000 ,GFP_KERNEL ,1000 ,NULL ); }while (nr_objects >10 ); }Index:
linux-2.6/include/linux/mm.h
===================================================================include/linux/mm.h +1
-1@@ -1118,7 +1118,7 @@ int in_gate_area_no_task(unsigned long aint drop_caches_sysctl_handler (struct ctl_table *,int ,struct file *,void __user *,size_t *,loff_t *);unsigned long shrink_slab (unsigned long scanned,gfp_t gfp_mask, -unsigned long lru_pages); +unsigned long lru_pages,struct zone *z);void drop_pagecache (void );void drop_slab (void );Index:
linux-2.6/include/linux/slab.h
===================================================================include/linux/slab.h +1
-0@@ -63,6 +63,7 @@ void kmem_cache_free(struct kmem_cache *unsigned int kmem_cache_size (struct kmem_cache *);const char *kmem_cache_name (struct kmem_cache *);int kmem_ptr_validate (struct kmem_cache *cachep,const void *ptr); +int kmem_cache_defrag (int node);/* * Please use this macro to create slab caches. Simply specify the Index:
linux-2.6/mm/vmscan.c
===================================================================mm/vmscan.c +9
-1@@ -150,10 +150,18 @@ EXPORT_SYMBOL(unregister_shrinker);* are eligible for the caller's allocation attempt. It is used for balancing * slab reclaim versus page reclaim. * +* zone is the zone for which we are shrinking the slabs. If the intent +* is to do a global shrink then zone may be NULL. Specification of a +* zone is currently only used to limit slab defragmentation to a NUMA node. +* The performace of shrink_slab would be better (in particular under NUMA) +* if it could be targeted as a whole to the zone that is under memory +* pressure but the VFS infrastructure does not allow that at the present +* time. +* * Returns the number of slab objects which we shrunk. */ unsigned long shrink_slab (unsigned long scanned,gfp_t gfp_mask, -unsigned long lru_pages) +unsigned long lru_pages,struct zone *zone) {struct shrinker *shrinker;unsigned long ret =0 ;
mm/vmscan.c unsigned long shrink_slab(unsigned long · line 222
Quoted 5 lines
mm/vmscan.c +2
-0@@ -210,6 +218,8 @@ unsigned long shrink_slab(unsigned long shrinker->nr += total_scan; }up_read (&shrinker_rwsem); +if (gfp_mask & __GFP_FS) +kmem_cache_defrag (zone ?zone_to_nid (zone) :-1 );
Does this make an assumption that only filesystem-related slabs may be targetted for reclaim? What if there is a slab that can free its objects without ever caring about a filesystem?
Quoted 62 lines
mm/vmscan.c +8
-6return ret; }@@ -1241,7 +1251,7 @@ unsigned long try_to_free_pages(struct zif (!priority)disable_swap_token (); nr_reclaimed +=shrink_zones (priority, zones, &sc); -shrink_slab (sc.nr_scanned, gfp_mask, lru_pages); +shrink_slab (sc.nr_scanned, gfp_mask, lru_pages,NULL );if (reclaim_state) { nr_reclaimed += reclaim_state->reclaimed_slab; reclaim_state->reclaimed_slab =0 ;@@ -1419,7 +1429,7 @@ loop_again: nr_reclaimed +=shrink_zone (priority, zone, &sc); reclaim_state->reclaimed_slab =0 ; nr_slab =shrink_slab (sc.nr_scanned,GFP_KERNEL , - lru_pages); + lru_pages, zone); nr_reclaimed += reclaim_state->reclaimed_slab; total_scanned += sc.nr_scanned;if (zone_is_all_unreclaimable (zone))@@ -1658,7 +1668,7 @@ unsigned long shrink_all_memory(unsigned/* If slab caches are huge, it's better to hit them first */ while (nr_slab >= lru_pages) { reclaim_state.reclaimed_slab =0 ; -shrink_slab (nr_pages, sc.gfp_mask, lru_pages); +shrink_slab (nr_pages, sc.gfp_mask, lru_pages,NULL );if (!reclaim_state.reclaimed_slab)break ;@@ -1696,7 +1706,7 @@ unsigned long shrink_all_memory(unsigned reclaim_state.reclaimed_slab =0 ;shrink_slab (sc.nr_scanned, sc.gfp_mask, -count_lru_pages ()); +count_lru_pages (),NULL ); ret += reclaim_state.reclaimed_slab;if (ret >= nr_pages) goto out;@@ -1713,7 +1723,8 @@ unsigned long shrink_all_memory(unsignedif (!ret) {do { reclaim_state.reclaimed_slab =0 ; -shrink_slab (nr_pages, sc.gfp_mask,count_lru_pages ()); +shrink_slab (nr_pages, sc.gfp_mask, +count_lru_pages (),NULL ); ret += reclaim_state.reclaimed_slab; }while (ret < nr_pages && reclaim_state.reclaimed_slab >0 ); }@@ -1875,7 +1886,8 @@ static int __zone_reclaim(struct zone *z* Note that shrink_slab will free memory on all zones and may * take a long time. */ -while (shrink_slab (sc.nr_scanned, gfp_mask, order) && +while (shrink_slab (sc.nr_scanned, gfp_mask, order, + zone) &&zone_page_state (zone,NR_SLAB_RECLAIMABLE ) > slab_reclaimable - nr_pages) ;Signature · 1 line
--
Signature · 10 lines
-- Mel Gorman Part-time Phd Student Linux Technology Center University of Limerick IBM Dublin Software Lab -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 12/23] SLUB: Trigger defragmentation from memory reclaim
Quoted 7 lines · Mel Gorman
mm/vmscan.c unsigned long shrink_slab(unsigned long · line 222
Quoted 3 lines
mm/vmscan.c +2
-0up_read (&shrinker_rwsem); +if (gfp_mask & __GFP_FS) +kmem_cache_defrag (zone ?zone_to_nid (zone) :-1 );Does this make an assumption that only filesystem-related slabs may be targetted for reclaim? What if there is a slab that can free its objects without ever caring about a filesystem?
Correct. Currently only filesystem related slabs support slab defragy.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 13/23 Buffer heads: Support slab defrag
In reply to Christoph LameterDefragmentation support for buffer heads. We convert the references to buffers to struct page references and try to remove the buffers from those pages. If the pages are dirty then trigger writeout so that the buffer heads can be removed later.
--- fs/buffer.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-)
fs/buffer.c +102 -1
@@ -3213,7 +3213,7 @@ static int buffer_cpu_notify(struct noti }static void -init_buffer_head (void *data,struct kmem_cache *cachep,unsigned long flags) +init_buffer_head (struct kmem_cache *cachep,void *data) {struct buffer_head * bh = (struct buffer_head *)data;
@@ -3221,6 +3221,106 @@ init_buffer_head(void *data, struct kmemINIT_LIST_HEAD (&bh->b_assoc_buffers); } +/* +* Writeback a page to clean the dirty state +*/ +static void trigger_write (struct page *page) +{ +struct address_space *mapping =page_mapping (page); +int rc; +struct writeback_control wbc = { + .sync_mode =WB_SYNC_NONE , + .nr_to_write =1 , + .range_start =0 , + .range_end =LLONG_MAX , + .nonblocking =1 , + .for_reclaim =0 + }; + +if (!mapping->a_ops->writepage) +/* No write method for the address space */ +return ; + +if (!clear_page_dirty_for_io (page)) +/* Someone else already triggered a write */ +return ; + + rc = mapping->a_ops->writepage (page, &wbc); +if (rc <0 ) +/* I/O Error writing */ +return ; + +if (rc ==AOP_WRITEPAGE_ACTIVATE ) +unlock_page (page); +} + +/* +* Get references on buffers. +* +* We obtain references on the page that uses the buffer. v[i] will point to +* the corresponding page after get_buffers() is through. +* +* We are safe from the underlying page being removed simply by doing +* a get_page_unless_zero. The buffer head removal may race at will. +* try_to_free_buffes will later take appropriate locks to remove the +* buffers if they are still there. +*/ +static void *get_buffers (struct kmem_cache *s,int nr,void **v) +{ +struct page *page; +struct buffer_head *bh; +int i,j; +int n =0 ; + +for (i =0 ; i < nr; i++) { + bh = v[i]; + v[i] =NULL ; + + page = bh->b_page; + +if (page &&PagePrivate (page)) { +for (j =0 ; j < n; j++) +if (page == v[j]) + goto cont; + } + +if (get_page_unless_zero (page)) + v[n++] = page; +cont: ; + } +return NULL ; +} + +/* +* Despite its name: kick_buffers operates on a list of pointers to +* page structs that was setup by get_buffer +*/ +static void kick_buffers (struct kmem_cache *s,int nr,void **v, +void *private) +{ +struct page *page; +int i; + +for (i =0 ; i < nr; i++) { + page = v[i]; + +if (!page ||PageWriteback (page)) +continue ; + + +if (!TestSetPageLocked (page)) { +if (PageDirty (page)) +trigger_write (page); +else { +if (PagePrivate (page)) +try_to_free_buffers (page); +unlock_page (page); + } + } +put_page (page); + } +} +void __init buffer_init (void ) {int nrpages;
@@ -3230,6 +3330,7 @@ void __init buffer_init(void) (SLAB_RECLAIM_ACCOUNT |SLAB_PANIC |SLAB_MEM_SPREAD ), init_buffer_head); +kmem_cache_setup_defrag (bh_cachep, get_buffers, kick_buffers);/* * Limit the bh occupancy to 10% of ZONE_NORMAL
PATCH 14/23 inodes: Support generic defragmentation
In reply to Christoph LameterThis implements the ability to remove inodes in a particular slab from inode cache. In order to remove an inode we may have to write out the pages of an inode, the inode itself and remove the dentries referring to the node.
Provide generic functionality that can be used by filesystems that have their own inode caches to also tie into the defragmentation functions that are made available here.
--- fs/inode.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 6 +++ 2 files changed, 102 insertions(+)
fs/inode.c +96 -0
@@ -1369,6 +1369,101 @@ static int __init set_ihash_entries(char }__setup ("ihash_entries=" , set_ihash_entries); +void *get_inodes (struct kmem_cache *s,int nr,void **v) +{ +int i; + +spin_lock (&inode_lock); +for (i =0 ; i < nr; i++) { +struct inode *inode = v[i]; + +if (inode->i_state & (I_FREEING |I_CLEAR |I_WILL_FREE )) + v[i] =NULL ; +else +__iget (inode); + } +spin_unlock (&inode_lock); +return NULL ; +} +EXPORT_SYMBOL (get_inodes); + +/* +* Function for filesystems that embedd struct inode into their own +* structures. The offset is the offset of the struct inode in the fs inode. +*/ +void *fs_get_inodes (struct kmem_cache *s,int nr,void **v, +unsigned long offset) +{ +int i; + +for (i =0 ; i < nr; i++) + v[i] += offset; + +return get_inodes (s, nr, v); +} +EXPORT_SYMBOL (fs_get_inodes); + +void kick_inodes (struct kmem_cache *s,int nr,void **v,void *private) +{ +struct inode *inode; +int i; +int abort =0 ; +LIST_HEAD (freeable); +struct super_block *sb; + +for (i =0 ; i < nr; i++) { + inode = v[i]; +if (!inode) +continue ; + +if (inode_has_buffers (inode) || inode->i_data.nrpages) { +if (remove_inode_buffers (inode)) +invalidate_mapping_pages (&inode->i_data, +0 ,-1 ); + } + +/* Invalidate children and dentry */ +if (S_ISDIR (inode->i_mode)) { +struct dentry *d =d_find_alias (inode); + +if (d) { +d_invalidate (d); +dput (d); + } + } + +if (inode->i_state &I_DIRTY ) +write_inode_now (inode,1 ); + +d_prune_aliases (inode); + } + +mutex_lock (&iprune_mutex); +for (i =0 ; i < nr; i++) { + inode = v[i]; +if (!inode) +continue ; + + sb = inode->i_sb; +iput (inode); +if (abort || !(sb->s_flags &MS_ACTIVE )) +continue ; + +spin_lock (&inode_lock); + abort = !can_unuse (inode); + +if (!abort) { +list_move (&inode->i_list, &freeable); + inode->i_state |=I_FREEING ; + inodes_stat.nr_unused--; + } +spin_unlock (&inode_lock); + } +dispose_list (&freeable); +mutex_unlock (&iprune_mutex); +} +EXPORT_SYMBOL (kick_inodes); +/* * Initialize the waitqueues and inode hash table. */
@@ -1408,6 +1503,7 @@ void __init inode_init(void) SLAB_MEM_SPREAD), init_once);register_shrinker (&icache_shrinker); +kmem_cache_setup_defrag (inode_cachep, get_inodes, kick_inodes);/* Hash may have been set up in inode_init_early */ if (!hashdist)
include/linux/fs.h +6 -0
@@ -1776,6 +1776,12 @@ static inline void insert_inode_hash(str__insert_inode_hash (inode, inode->i_ino); } +/* Helper functions for inode defragmentation support in filesystems */ +extern void kick_inodes (struct kmem_cache *,int ,void **,void *); +extern void *get_inodes (struct kmem_cache *,int nr,void **); +extern void *fs_get_inodes (struct kmem_cache *,int nr,void **, +unsigned long offset); +extern struct file *get_empty_filp (void );extern void file_move (struct file *f,struct list_head *list);extern void file_kill (struct file *f);
Re: [patch 14/23] inodes: Support generic defragmentation
Quoted 8 lines · Christoph Lameter
fs/inode.c +7
-0+void *get_inodes (struct kmem_cache *s,int nr,void **v) +{ +int i; + +spin_lock (&inode_lock); +for (i =0 ; i < nr; i++) { +struct inode *inode = v[i];
fs/inode.c static int __init set_ihash_entries(char · line 1388
Quoted 10 lines
fs/inode.c +10
-0+ +if (inode->i_state & (I_FREEING |I_CLEAR |I_WILL_FREE )) + v[i] =NULL ; +else +__iget (inode); + } +spin_unlock (&inode_lock); +return NULL ; +} +EXPORT_SYMBOL (get_inodes);
What purpose does the return type have?
Quoted 5 lines
fs/inode.c +5
-0+/* +* Function for filesystems that embedd struct inode into their own +* structures. The offset is the offset of the struct inode in the fs inode. +*/ +void *fs_get_inodes(struct kmem_cache *s, int nr, void **v,
fs/inode.c static int __init set_ihash_entries(char · line 1404
Quoted 10 lines
fs/inode.c +10
-0+ unsigned long offset) +{ +int i; + +for (i =0 ; i < nr; i++) + v[i] += offset; + +return get_inodes (s, nr, v); +} +EXPORT_SYMBOL (fs_get_inodes);
The fact that all pointers get changed makes me a bit uneasy:
struct foo_inode v[20]; ... fs_get_inodes(..., v, ...); ... v[0].foo_field = bar;
No warning, but spectacular fireworks.
fs/inode.c static int __init set_ihash_entries(char · line 1417
Quoted 12 lines
fs/inode.c +12
-0+void kick_inodes (struct kmem_cache *s,int nr,void **v,void *private) +{ +struct inode *inode; +int i; +int abort =0 ; +LIST_HEAD (freeable); +struct super_block *sb; + +for (i =0 ; i < nr; i++) { + inode = v[i]; +if (!inode) +continue ;
NULL is legal here? Then fs_get_inodes should check for NULL as well and not add the offset to NULL pointers, I guess.
fs/inode.c static int __init set_ihash_entries(char · line 1422
Quoted 4 lines
fs/inode.c +4
-0+if (inode_has_buffers (inode) || inode->i_data.nrpages) { +if (remove_inode_buffers (inode)) +invalidate_mapping_pages (&inode->i_data, +0 ,-1 );
This linebreak can be removed.
Quoted 4 lines
fs/inode.c +4
-0+ } + +/* Invalidate children and dentry */ +if (S_ISDIR (inode->i_mode)) {
fs/inode.c static int __init set_ihash_entries(char · line 1436
Quoted 10 lines
fs/inode.c +10
-0+struct dentry *d =d_find_alias (inode); + +if (d) { +d_invalidate (d); +dput (d); + } + } + +if (inode->i_state &I_DIRTY ) +write_inode_now (inode,1 );
Once more the three-bit I_DIRTY is used like a boolean value. I don't hold it against you, specifically. A general review/cleanup is necessary for that.
JA?rn
Signature · 9 lines
"[One] doesn't need to know [...] how to cause a headache in order to take an aspirin." -- Scott Culp, Manager of the Microsoft Security Response Center, 2001 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 14/23] inodes: Support generic defragmentation
Quoted 25 lines · JA?rn Engel
Quoted 5 lines
fs/inode.c +5
-0+/* +* Function for filesystems that embedd struct inode into their own +* structures. The offset is the offset of the struct inode in the fs inode. +*/ +void *fs_get_inodes(struct kmem_cache *s, int nr, void **v,fs/inode.c static int __init set_ihash_entries(char · line 1404
Quoted 10 lines
fs/inode.c +10
-0+ unsigned long offset) +{ +int i; + +for (i =0 ; i < nr; i++) + v[i] += offset; + +return get_inodes (s, nr, v); +} +EXPORT_SYMBOL (fs_get_inodes);The fact that all pointers get changed makes me a bit uneasy:
struct foo_inode v[20]; ... fs_get_inodes(..., v, ...); ... v[0].foo_field = bar;No warning, but spectacular fireworks.
Quoted 15 lines
fs/inode.c static int __init set_ihash_entries(char · line 1417
Quoted 12 lines
fs/inode.c +12
-0+void kick_inodes (struct kmem_cache *s,int nr,void **v,void *private) +{ +struct inode *inode; +int i; +int abort =0 ; +LIST_HEAD (freeable); +struct super_block *sb; + +for (i =0 ; i < nr; i++) { + inode = v[i]; +if (!inode) +continue ;NULL is legal here? Then
fs_get_inodesshould check for NULL as well and not add the offset to NULL pointers, I guess.
Ignore these two comments. Reading further before making them would have helped. ;)
JA?rn
Signature · 10 lines
Fancy algorithms are slow when n is small, and n is usually small. Fancy algorithms have big constants. Until you know that n is frequently going to be big, don't get fancy. -- Rob Pike -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 14/23] inodes: Support generic defragmentation
In reply to Jörn EngelQuoted 19 lines · Jorn Engel
Quoted 6 lines · Christoph Lameter
fs/inode.c +5
-0+/* +* Function for filesystems that embedd struct inode into their own +* structures. The offset is the offset of the struct inode in the fs inode. +*/ +void *fs_get_inodes(struct kmem_cache *s, int nr, void **v,fs/inode.c static int __init set_ihash_entries(char · line 1404
Quoted 10 lines
fs/inode.c +10
-0+ unsigned long offset) +{ +int i; + +for (i =0 ; i < nr; i++) + v[i] += offset; + +return get_inodes (s, nr, v); +} +EXPORT_SYMBOL (fs_get_inodes);The fact that all pointers get changed makes me a bit uneasy:
Quoted 7 lines
struct foo_inode v[20]; ... fs_get_inodes(..., v, ...); ... v[0].foo_field = bar;No warning, but spectacular fireworks.
You'l get a warning that struct foo_inode * is incompatible with void **.
Andreas.
Signature · 10 lines
Andreas Schwab, SuSE Labs, [email protected] SuSE Linux Products GmbH, Maxfeldstrasse 5, 90409 Nurnberg, Germany PGP key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different." -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 14/23] inodes: Support generic defragmentation
Quoted 11 lines · Andreas Schwab
Quoted 9 lines
The fact that all pointers get changed makes me a bit uneasy:
struct foo_inode v[20]; ... fs_get_inodes(..., v, ...); ... v[0].foo_field = bar;No warning, but spectacular fireworks.
You'l get a warning that struct
foo_inode* is incompatible with void **.
- struct foo_inode v[20];
+ struct foo_inode *v[20];
Looks like my example needs a patch as well. Anyway, the function is used in a way that makes this a non-issue.
JA?rn
Signature · 10 lines
You cannot suppose that Moliere ever troubled himself to be original in the matter of ideas. You cannot suppose that the stories he tells in his plays have never been told before. They were culled, as you very well know. -- Andre-Louis Moreau in Scarabouche -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 14/23] inodes: Support generic defragmentation
In reply to Jörn EngelQuoted 13 lines · Jörn Engel
Quoted 12 lines · Christoph Lameter
fs/inode.c +11
-0+void *get_inodes (struct kmem_cache *s,int nr,void **v) +{ +int i; + +spin_lock (&inode_lock); +for (i =0 ; i < nr; i++) { +struct inode *inode = v[i]; + +if (inode->i_state & (I_FREEING |I_CLEAR |I_WILL_FREE )) + v[i] =NULL ; +else
Quoted 8 lines
fs/inode.c static int __init set_ihash_entries(char · line 1388
Quoted 6 lines
fs/inode.c +6
-0+__iget (inode); + } +spin_unlock (&inode_lock); +return NULL ; +} +EXPORT_SYMBOL (get_inodes);What purpose does the return type have?
The pointer is for communication between the get and kick methods. get() can modify kick() behavior by returning a pointer to a data structure or using the pointer to set a flag. F.e. get() may discover that there is an unreclaimable object and set a flag that causes kick to simply undo the refcount increment. get() may build a map for the objects and indicate in the map special treatment.
Quoted 13 lines
fs/inode.c static int __init set_ihash_entries(char · line 1404
Quoted 11 lines
fs/inode.c +11
-0+void *fs_get_inodes (struct kmem_cache *s,int nr,void **v, +unsigned long offset) +{ +int i; + +for (i =0 ; i < nr; i++) + v[i] += offset; + +return get_inodes (s, nr, v); +} +EXPORT_SYMBOL (fs_get_inodes);The fact that all pointers get changed makes me a bit uneasy:
Quoted 7 lines
struct foo_inode v[20]; ... fs_get_inodes(..., v, ...); ... v[0].foo_field = bar;No warning, but spectacular fireworks.
As far as I can remember: The core code always passes pointers to struct inode to the filesystems. The filesystems will then recalculate the pointers to point to the fs ide of an inode.
Quoted 7 lines
Quoted 7 lines
fs/inode.c +7
-0+void kick_inodes (struct kmem_cache *s,int nr,void **v,void *private) +{ +struct inode *inode; +int i; +int abort =0 ; +LIST_HEAD (freeable); +struct super_block *sb;
Quoted 8 lines
fs/inode.c static int __init set_ihash_entries(char · line 1417
Quoted 5 lines
fs/inode.c +5
-0+ +for (i =0 ; i < nr; i++) { + inode = v[i]; +if (!inode) +continue ;NULL is legal here? Then
fs_get_inodesshould check for NULL as well and not add the offset to NULL pointers, I guess.
The get() method may have set a pointer to NULL. The fs_get_inodes() is run at a time when all pointers are valid.
Quoted 10 lines
Quoted 10 lines
fs/inode.c +10
-0+ } + +/* Invalidate children and dentry */ +if (S_ISDIR (inode->i_mode)) { +struct dentry *d =d_find_alias (inode); + +if (d) { +d_invalidate (d); +dput (d); + }
Quoted 8 lines
fs/inode.c static int __init set_ihash_entries(char · line 1436
Quoted 4 lines
fs/inode.c +4
-0+ } + +if (inode->i_state &I_DIRTY ) +write_inode_now (inode,1 );Once more the three-bit
I_DIRTYis used like a boolean value. I don't hold it against you, specifically. A general review/cleanup is necessary for that.
Yeah. I'd be glad if someone could take this piece off my hands.
Re: [patch 14/23] inodes: Support generic defragmentation
Quoted 23 lines · Christoph Lameter
Quoted 13 lines · JA?rn Engel
Quoted 12 lines · Christoph Lameter
fs/inode.c +11
-0+void *get_inodes (struct kmem_cache *s,int nr,void **v) +{ +int i; + +spin_lock (&inode_lock); +for (i =0 ; i < nr; i++) { +struct inode *inode = v[i]; + +if (inode->i_state & (I_FREEING |I_CLEAR |I_WILL_FREE )) + v[i] =NULL ; +else Quoted 8 lines
fs/inode.c static int __init set_ihash_entries(char · line 1388
Quoted 6 lines
fs/inode.c +6
-0+__iget (inode); + } +spin_unlock (&inode_lock); +return NULL ; +} +EXPORT_SYMBOL (get_inodes);What purpose does the return type have?
Quoted 6 lines
The pointer is for communication between the get and kick methods.
get()can modifykick()behavior by returning a pointer to a data structure or using the pointer to set a flag. F.e.get()may discover that there is an unreclaimable object and set a flag that causes kick to simply undo the refcount increment.get()may build a map for the objects and indicate in the map special treatment.
Is there a get/kick pair that actually does this? So far I haven't found anything like it.
Also, something vaguely matching that paragraph might make sense in a kerneldoc header to the function. ;)
JA?rn
Signature · 9 lines
There is no worse hell than that provided by the regrets for wasted opportunities. -- Andre-Louis Moreau in Scarabouche -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 14/23] inodes: Support generic defragmentation
Quoted 9 lines · Jörn Engel
Quoted 6 lines
The pointer is for communication between the get and kick methods.
get()can modifykick()behavior by returning a pointer to a data structure or using the pointer to set a flag. F.e.get()may discover that there is an unreclaimable object and set a flag that causes kick to simply undo the refcount increment.get()may build a map for the objects and indicate in the map special treatment.Is there a get/kick pair that actually does this? So far I haven't found anything like it.
Hmmm.. Nothing uses it at this point. I went through a series of get/kicks during development. Some needed it. I suspect that we will need it when we implement reallocation instead of simply reclaiming. It is also necessary if we get into the situation where we want to optimize the reclaim. At that point the kick method needs to know how far get() got before the action was aborted in order to fix up only certain refcounts.
Quoted 2 lines
Also, something vaguely matching that paragraph might make sense in a kerneldoc header to the function. ;)
Its described in slab.h
PATCH 15/23 FS: ExtX filesystem defrag
In reply to Christoph LameterSupport defragmentation for extX filesystem inodes
--- fs/ext2/super.c | 9 +++++++++ fs/ext3/super.c | 8 ++++++++ fs/ext4/super.c | 8 ++++++++ 3 files changed, 25 insertions(+)
fs/ext2/super.c +9 -0
@@ -171,6 +171,12 @@ static void init_once(struct kmem_cacheinode_init_once (&ei->vfs_inode); } +static void *ext2_get_inodes (struct kmem_cache *s,int nr,void **v) +{ +return fs_get_inodes (s, nr, v, + offsetof(struct ext2_inode_info , vfs_inode)); +} +static int init_inodecache (void ) { ext2_inode_cachep = kmem_cache_create("ext2_inode_cache",
@@ -180,6 +186,9 @@ static int init_inodecache(void) init_once);if (ext2_inode_cachep ==NULL )return -ENOMEM ; + +kmem_cache_setup_defrag (ext2_inode_cachep, + ext2_get_inodes, kick_inodes);return 0 ; }
fs/ext3/super.c +8 -0
@@ -484,6 +484,12 @@ static void init_once(struct kmem_cacheinode_init_once (&ei->vfs_inode); } +static void *ext3_get_inodes (struct kmem_cache *s,int nr,void **v) +{ +return fs_get_inodes (s, nr, v, + offsetof(struct ext3_inode_info , vfs_inode)); +} +static int init_inodecache (void ) { ext3_inode_cachep = kmem_cache_create("ext3_inode_cache",
@@ -493,6 +499,8 @@ static int init_inodecache(void) init_once);if (ext3_inode_cachep ==NULL )return -ENOMEM ; +kmem_cache_setup_defrag (ext3_inode_cachep, + ext3_get_inodes, kick_inodes);return 0 ; }
fs/ext4/super.c +8 -0
@@ -537,6 +537,12 @@ static void init_once(struct kmem_cacheinode_init_once (&ei->vfs_inode); } +static void *ext4_get_inodes (struct kmem_cache *s,int nr,void **v) +{ +return fs_get_inodes (s, nr, v, + offsetof(struct ext4_inode_info , vfs_inode)); +} +static int init_inodecache (void ) { ext4_inode_cachep = kmem_cache_create("ext4_inode_cache",
@@ -546,6 +552,8 @@ static int init_inodecache(void) init_once);if (ext4_inode_cachep ==NULL )return -ENOMEM ; +kmem_cache_setup_defrag (ext4_inode_cachep, + ext4_get_inodes, kick_inodes);return 0 ; }
PATCH 16/23 FS: XFS slab defragmentation
In reply to Christoph LameterSupport inode defragmentation for xfs
--- fs/xfs/linux-2.6/xfs_super.c | 1 + 1 file changed, 1 insertion(+)
fs/xfs/linux-2.6/xfs_super.c +1 -0
@@ -374,6 +374,7 @@ xfs_init_zones(void) xfs_ioend_zone =kmem_zone_init (sizeof (xfs_ioend_t),"xfs_ioend" );if (!xfs_ioend_zone) goto out_destroy_vnode_zone; +kmem_cache_setup_defrag (xfs_vnode_zone, get_inodes, kick_inodes); xfs_ioend_pool =mempool_create_slab_pool (4 *MAX_BUF_PER_PAGE , xfs_ioend_zone);
PATCH 17/23 FS: Proc filesystem support for slab defrag
In reply to Christoph LameterSupport procfs inode defragmentation
--- fs/proc/inode.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/proc/inode.c +8 -0
@@ -114,6 +114,12 @@ static void init_once(struct kmem_cacheinode_init_once (&ei->vfs_inode); } +static void *proc_get_inodes (struct kmem_cache *s,int nr,void **v) +{ +return fs_get_inodes (s, nr, v, + offsetof(struct proc_inode , vfs_inode)); +}; +int __init proc_init_inodecache (void ) { proc_inode_cachep = kmem_cache_create("proc_inode_cache",
@@ -121,6 +127,8 @@ int __init proc_init_inodecache(void)0 , (SLAB_RECLAIM_ACCOUNT |SLAB_MEM_SPREAD |SLAB_PANIC ), init_once); +kmem_cache_setup_defrag (proc_inode_cachep, + proc_get_inodes, kick_inodes);return 0 ; }
PATCH 18/23 FS: Slab defrag: Reiserfs support
In reply to Christoph LameterSlab defragmentation: Support reiserfs inode defragmentation
--- fs/reiserfs/super.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/reiserfs/super.c +8 -0
@@ -532,6 +532,12 @@ static void init_once(struct kmem_cache#endif } +static void *reiserfs_get_inodes (struct kmem_cache *s,int nr,void **v) +{ +return fs_get_inodes (s, nr, v, + offsetof(struct reiserfs_inode_info , vfs_inode)); +} +static int init_inodecache (void ) { reiserfs_inode_cachep = kmem_cache_create("reiser_inode_cache",
@@ -542,6 +548,8 @@ static int init_inodecache(void) init_once);if (reiserfs_inode_cachep ==NULL )return -ENOMEM ; +kmem_cache_setup_defrag (reiserfs_inode_cachep, + reiserfs_get_inodes, kick_inodes);return 0 ; }
PATCH 19/23 FS: Socket inode defragmentation
In reply to Christoph LameterSupport inode defragmentation for sockets
--- net/socket.c | 8 ++++++++ 1 file changed, 8 insertions(+)
net/socket.c +8 -0
@@ -265,6 +265,12 @@ static void init_once(struct kmem_cacheinode_init_once (&ei->vfs_inode); } +static void *sock_get_inodes (struct kmem_cache *s,int nr,void **v) +{ +return fs_get_inodes (s, nr, v, + offsetof(struct socket_alloc , vfs_inode)); +} +static int init_inodecache (void ) { sock_inode_cachep = kmem_cache_create("sock_inode_cache",
@@ -276,6 +282,8 @@ static int init_inodecache(void) init_once);if (sock_inode_cachep ==NULL )return -ENOMEM ; +kmem_cache_setup_defrag (sock_inode_cachep, + sock_get_inodes, kick_inodes);return 0 ; }
PATCH 20/23 dentries: Add constructor
In reply to Christoph LameterIn order to support defragmentation on the dentry cache we need to have a determined object state at all times. Without a constructor the object would have a random state after allocation.
So provide a constructor.
--- fs/dcache.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)
fs/dcache.c +14 -12
@@ -870,6 +870,16 @@ static struct shrinker dcache_shrinker = .seeks = DEFAULT_SEEKS, }; +void dcache_ctor (struct kmem_cache *s,void *p) +{ +struct dentry *dentry = p; + +spin_lock_init (&dentry->d_lock); + dentry->d_inode =NULL ; +INIT_LIST_HEAD (&dentry->d_lru); +INIT_LIST_HEAD (&dentry->d_alias); +} +/** * d_alloc - allocate a dcache entry * @parent: parent of entry to allocate
@@ -907,8 +917,6 @@ struct dentry *d_alloc(struct dentry * patomic_set (&dentry->d_count,1 ); dentry->d_flags =DCACHE_UNHASHED ; -spin_lock_init (&dentry->d_lock); - dentry->d_inode =NULL ; dentry->d_parent =NULL ; dentry->d_sb =NULL ; dentry->d_op =NULL ;
@@ -918,9 +926,7 @@ struct dentry *d_alloc(struct dentry * p dentry->d_cookie =NULL ;#endif INIT_HLIST_NODE (&dentry->d_hash); -INIT_LIST_HEAD (&dentry->d_lru);INIT_LIST_HEAD (&dentry->d_subdirs); -INIT_LIST_HEAD (&dentry->d_alias);if (parent) { dentry->d_parent =dget (parent);
@@ -2096,14 +2102,10 @@ static void __init dcache_init(void) {int loop; -/* -* A constructor could be added for stable state like the lists, -* but it is probably not worth it because of the cache nature -* of the dcache. -*/ - dentry_cache =KMEM_CACHE (dentry, -SLAB_RECLAIM_ACCOUNT |SLAB_PANIC |SLAB_MEM_SPREAD ); - + dentry_cache =kmem_cache_create ("dentry_cache" ,sizeof (struct dentry ), +0 ,SLAB_RECLAIM_ACCOUNT |SLAB_PANIC |SLAB_MEM_SPREAD , + dcache_ctor); +register_shrinker (&dcache_shrinker);/* Hash may have been set up in dcache_init_early */
Re: [patch 20/23] dentries: Add constructor
On (06/11/07 17:11), Christoph Lameter didst pronounce:
Quoted 8 lines
In order to support defragmentation on the dentry cache we need to have a determined object state at all times. Without a constructor the object would have a random state after allocation.
Reviewed-by Rik van Riel <[email protected]>So provide a constructor.
Signed-off-by Christoph Lameter <[email protected]>
Seems to be some garbling on there in the signed-off lines.
Quoted 12 lines
--- fs/dcache.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-)Index:
linux-2.6/fs/dcache.c
===================================================================fs/dcache.c +0
-0@@ -870,6 +870,16 @@ static struct shrinker dcache_shrinker = .seeks = DEFAULT_SEEKS, };
fs/dcache.c static struct shrinker dcache_shrinker = · line 882
Quoted 10 lines
fs/dcache.c +10
-0+void dcache_ctor (struct kmem_cache *s,void *p) +{ +struct dentry *dentry = p; + +spin_lock_init (&dentry->d_lock); + dentry->d_inode =NULL ; +INIT_LIST_HEAD (&dentry->d_lru); +INIT_LIST_HEAD (&dentry->d_alias); +} +
Is there any noticable overhead to the constructor?
Quoted 41 lines
fs/dcache.c +4
-12/** * d_alloc - allocate a dcache entry * @parent: parent of entry to allocate @@ -907,8 +917,6 @@ struct dentry *d_alloc(struct dentry * patomic_set (&dentry->d_count,1 ); dentry->d_flags =DCACHE_UNHASHED ; -spin_lock_init (&dentry->d_lock); - dentry->d_inode =NULL ; dentry->d_parent =NULL ; dentry->d_sb =NULL ; dentry->d_op =NULL ;@@ -918,9 +926,7 @@ struct dentry *d_alloc(struct dentry * p dentry->d_cookie =NULL ;#endif INIT_HLIST_NODE (&dentry->d_hash); -INIT_LIST_HEAD (&dentry->d_lru);INIT_LIST_HEAD (&dentry->d_subdirs); -INIT_LIST_HEAD (&dentry->d_alias);if (parent) { dentry->d_parent =dget (parent);@@ -2096,14 +2102,10 @@ static void __init dcache_init(void) {int loop; -/* -* A constructor could be added for stable state like the lists, -* but it is probably not worth it because of the cache nature -* of the dcache. -*/ - dentry_cache =KMEM_CACHE (dentry, -SLAB_RECLAIM_ACCOUNT |SLAB_PANIC |SLAB_MEM_SPREAD ); - + dentry_cache =kmem_cache_create ("dentry_cache" ,sizeof (struct dentry ), +0 ,SLAB_RECLAIM_ACCOUNT |SLAB_PANIC |SLAB_MEM_SPREAD , + dcache_ctor); +register_shrinker (&dcache_shrinker);/* Hash may have been set up in dcache_init_early */
Signature · 9 lines
Mel Gorman Part-time Phd Student Linux Technology Center University of Limerick IBM Dublin Software Lab -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 20/23] dentries: Add constructor
Quoted 3 lines · Mel Gorman
Quoted 1 line
Signed-off-by Christoph Lameter <[email protected]>Seems to be some garbling on there in the signed-off lines.
Yes that needs to be fixed.
Quoted 4 lines
Quoted 4 lines
fs/dcache.c +4
-0+void dcache_ctor (struct kmem_cache *s,void *p) +{ +struct dentry *dentry = p; +
Quoted 8 lines
fs/dcache.c static struct shrinker dcache_shrinker = · line 882
Quoted 6 lines
fs/dcache.c +6
-0+spin_lock_init (&dentry->d_lock); + dentry->d_inode =NULL ; +INIT_LIST_HEAD (&dentry->d_lru); +INIT_LIST_HEAD (&dentry->d_alias); +} +Is there any noticable overhead to the constructor?
Its a minor performance win since we can avoid reinitializing these values and zeroing the object on alloc if there are already allocated objects.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 21/23 dentries: dentry defragmentation
In reply to Christoph LameterThe dentry pruning for unused entries works in a straightforward way. It could be made more aggressive if one would actually move dentries instead of just reclaiming them.
--- fs/dcache.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 100 insertions(+), 1 deletion(-)
fs/dcache.c +100 -1
@@ -31,6 +31,7 @@#include <linux/seqlock.h> #include <linux/swap.h> #include <linux/bootmem.h> +#include <linux/backing-dev.h> #include "internal.h"
@@ -143,7 +144,10 @@ static struct dentry *d_kill(struct dentlist_del (&dentry->d_u.d_child); dentry_stat.nr_dentry--;/* For d_free, below */ -/*drops the locks, at that point nobody can reach this dentry */ +/* +* drops the locks, at that point nobody (aside from defrag) +* can reach this dentry +*/ dentry_iput (dentry); parent = dentry->d_parent;d_free (dentry);
@@ -2098,6 +2102,100 @@ static void __init dcache_init_early(voiINIT_HLIST_HEAD (&dentry_hashtable[loop]); } +/* +* The slab allocator is holding off frees. We can safely examine +* the object without the danger of it vanishing from under us. +*/ +static void *get_dentries (struct kmem_cache *s,int nr,void **v) +{ +struct dentry *dentry; +int i; + +spin_lock (&dcache_lock); +for (i =0 ; i < nr; i++) { + dentry = v[i]; + +/* +* Three sorts of dentries cannot be reclaimed: +* +* 1. dentries that are in the process of being allocated +* or being freed. In that case the dentry is neither +* on the LRU nor hashed. +* +* 2. Fake hashed entries as used for anonymous dentries +* and pipe I/O. The fake hashed entries have d_flags +* set to indicate a hashed entry. However, the +* d_hash field indicates that the entry is not hashed. +* +* 3. dentries that have a backing store that is not +* writable. This is true for tmpsfs and other in +* memory filesystems. Removing dentries from them +* would loose dentries for good. +*/ +if ((d_unhashed (dentry) &&list_empty (&dentry->d_lru)) || + (!d_unhashed (dentry) &&hlist_unhashed (&dentry->d_hash)) || + (dentry->d_inode && + !mapping_cap_writeback_dirty (dentry->d_inode->i_mapping))) +/* Ignore this dentry */ + v[i] =NULL ; +else +/* dget_locked will remove the dentry from the LRU */ +dget_locked (dentry); + } +spin_unlock (&dcache_lock); +return NULL ; +} + +/* +* Slab has dropped all the locks. Get rid of the refcount obtained +* earlier and also free the object. +*/ +static void kick_dentries (struct kmem_cache *s, +int nr,void **v,void *private) +{ +struct dentry *dentry; +int i; + +/* +* First invalidate the dentries without holding the dcache lock +*/ +for (i =0 ; i < nr; i++) { + dentry = v[i]; + +if (dentry) +d_invalidate (dentry); + } + +/* +* If we are the last one holding a reference then the dentries can +* be freed. We need the dcache_lock. +*/ +spin_lock (&dcache_lock); +for (i =0 ; i < nr; i++) { + dentry = v[i]; +if (!dentry) +continue ; + +spin_lock (&dentry->d_lock); +if (atomic_read (&dentry->d_count) >1 ) { +spin_unlock (&dentry->d_lock); +spin_unlock (&dcache_lock); +dput (dentry); +spin_lock (&dcache_lock); +continue ; + } + +prune_one_dentry (dentry); + } +spin_unlock (&dcache_lock); + +/* +* dentries are freed using RCU so we need to wait until RCU +* operations are complete +*/ +synchronize_rcu (); +} +static void __init dcache_init (void ) {int loop;
@@ -2107,6 +2205,7 @@ static void __init dcache_init(void) dcache_ctor);register_shrinker (&dcache_shrinker); +kmem_cache_setup_defrag (dentry_cache, get_dentries, kick_dentries);/* Hash may have been set up in dcache_init_early */ if (!hashdist)
PATCH 22/23 SLUB: Slab reclaim through Lumpy reclaim
In reply to Christoph LameterCreates a special function kmem_cache_isolate_slab() and kmem_cache_reclaim() to support lumpy reclaim.
In order to isolate pages we will have to handle slab page allocations in such a way that we can determine if a slab is valid whenever we access it regardless of its time in life.
A valid slab that can be freed has PageSlab(page) and page->inuse > 0 set. So we need to make sure in allocate_slab() that page->inuse is zero before PageSlab is set.
kmem_cache_isolate_page() is called from lumpy reclaim to isolate pages neighboring a page cache page that is being reclaimed. Lumpy reclaim will gather the slabs and call kmem_cache_reclaim() on the list.
This means that we can remove a slab in order to be able to coalesce a higher order page.
--- include/linux/slab.h | 2 + mm/slab.c | 13 ++++++ mm/slub.c | 102 ++++++++++++++++++++++++++++++++++++++++++++++++--- mm/vmscan.c | 13 +++++- 4 files changed, 123 insertions(+), 7 deletions(-)
include/linux/slab.h +2 -0
@@ -64,6 +64,8 @@ unsigned int kmem_cache_size(struct kmemconst char *kmem_cache_name (struct kmem_cache *);int kmem_ptr_validate (struct kmem_cache *cachep,const void *ptr);int kmem_cache_defrag (int node); +int kmem_cache_isolate_slab (struct page *); +int kmem_cache_reclaim (struct list_head *);/* * Please use this macro to create slab caches. Simply specify the
mm/slab.c +13 -0
@@ -2559,6 +2559,19 @@ int kmem_cache_defrag(int node)return 0 ; } +/* +* SLAB does not support slab defragmentation +*/ +int kmem_cache_isolate_slab (struct page *page) +{ +return -ENOSYS ; +} + +int kmem_cache_reclaim (struct list_head *zaplist) +{ +return 0 ; +} +/** * kmem_cache_destroy - delete a cache * @cachep: the cache to destroy
mm/slub.c +97 -5
129 lines not on this page · raw message
mm/vmscan.c +11 -2
@@ -687,6 +687,7 @@ static int __isolate_lru_page(struct pag*/ static unsigned long isolate_lru_pages (unsigned long nr_to_scan,struct list_head *src,struct list_head *dst, +struct list_head *slab_pages,unsigned long *scanned,int order,int mode) {unsigned long nr_taken =0 ;
@@ -760,7 +761,13 @@ static unsigned long isolate_lru_pages(ucase -EBUSY :/* else it is being freed elsewhere */ list_move (&cursor_page->lru, src); +break ; +default : +if (slab_pages && +kmem_cache_isolate_slab (cursor_page) ==0 ) +list_add (&cursor_page->lru, + slab_pages);break ; } }
@@ -796,6 +803,7 @@ static unsigned long shrink_inactive_lis struct zone *zone, struct scan_control *sc) {LIST_HEAD (page_list ); +LIST_HEAD (slab_list);struct pagevec pvec;unsigned long nr_scanned =0 ;unsigned long nr_reclaimed =0 ;
@@ -813,7 +821,7 @@ static unsigned long shrink_inactive_lis nr_taken =isolate_lru_pages (sc->swap_cluster_max, &zone->inactive_list, - &page_list, &nr_scan, sc->order, + &page_list, &slab_list, &nr_scan, sc->order, (sc->order >PAGE_ALLOC_COSTLY_ORDER )?ISOLATE_BOTH :ISOLATE_INACTIVE ); nr_active =clear_active_flags (&page_list);
@@ -824,6 +832,7 @@ static unsigned long shrink_inactive_lis -(nr_taken - nr_active)); zone->pages_scanned += nr_scan;spin_unlock_irq (&zone->lru_lock); +kmem_cache_reclaim (&slab_list); nr_scanned += nr_scan; nr_freed =shrink_page_list (&page_list, sc,PAGEOUT_IO_ASYNC );
@@ -1029,7 +1038,7 @@ force_reclaim_mapped:lru_add_drain ();spin_lock_irq (&zone->lru_lock); pgmoved =isolate_lru_pages (nr_pages, &zone->active_list, - &l_hold, &pgscanned, sc->order,ISOLATE_ACTIVE ); + &l_hold,NULL , &pgscanned, sc->order,ISOLATE_ACTIVE ); zone->pages_scanned += pgscanned;__mod_zone_page_state (zone,NR_ACTIVE , -pgmoved);spin_unlock_irq (&zone->lru_lock);
PATCH 23/23 SLUB: Add SlabReclaimable() to avoid repeated reclaim attempts
In reply to Christoph LameterAdd a flag RECLAIMABLE to be set on slabs with a defragmentation method
Clear the flag if a reclaim action is not successful in reducing the number of objects in a slab.
The reclaim flag is set again when all objeccts of the slab have been allocated and it is removed from the partial lists.
--- mm/slub.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-)
mm/slub.c +17 -3
@@ -102,6 +102,7 @@#define FROZEN (1 << PG_active)#define LOCKED (1 << PG_locked) +#define RECLAIMABLE (1 << PG_dirty)#ifdef CONFIG_SLUB_DEBUG #define SLABDEBUG (1 << PG_error)
@@ -1100,6 +1101,8 @@ static noinline struct page *new_slab(stif (s->flags & (SLAB_DEBUG_FREE |SLAB_RED_ZONE |SLAB_POISON |SLAB_STORE_USER |SLAB_TRACE )) state |=SLABDEBUG ; +if (s->kick) + state |=RECLAIMABLE ; start =page_address (page); page->end = start +1 ;
@@ -1176,6 +1179,7 @@ static void discard_slab(struct kmem_cacatomic_long_dec (&n->nr_slabs);reset_page_mapcount (page); + page->flags &= ~RECLAIMABLE ;__ClearPageSlab (page);free_slab (s, page); }
@@ -1408,8 +1412,11 @@ static void unfreeze_slab(struct kmem_caif (page->freelist != page->end)add_partial (s, page, tail); -else +else {add_full (s, page, state); +if (s->kick && !(state &RECLAIMABLE )) + state |=RECLAIMABLE ; + }slab_unlock (page, state); }else {
@@ -2633,7 +2640,7 @@ out:* Check if the given state is that of a reclaimable slab page. * * This is only true if this is indeed a slab page and if -* the page has not been frozen. +* the page has not been frozen or marked as unreclaimable. */ static inline int reclaimable_slab (unsigned long state) {
@@ -2643,7 +2650,7 @@ static inline int reclaimable_slab(unsigif (state &FROZEN )return 0 ; -return 1 ; +return state &RECLAIMABLE ; }/*
@@ -2958,6 +2965,8 @@ out:* Check the result and unfreeze the slab */ leftover = page->inuse; +if (leftover) + state &= ~RECLAIMABLE ;unfreeze_slab (s, page, leftover >0 , state);local_irq_restore (flags);return leftover;
@@ -3012,6 +3021,11 @@ static unsigned long __kmem_cache_shrinkif (!state)continue ; +if (!(state &RECLAIMABLE )) { +slab_unlock (page, state); +continue ; + } +if (page->inuse) {list_move (&page->lru, &zaplist);
Quoted 1 line · Christoph Lameter
Slab defragmentation
I thought we had agreed that: targeted reclaim, was a more suitable term for this work as it does not do compaction.
Quoted 5 lines · Peter Zijlstra
Quoted 1 line · Christoph Lameter
Slab defragmentation
I thought we had agreed that: targeted reclaim, was a more suitable term for this work as it does not do compaction.
It does compaction by removing less populated slabs. If a kick method reallocates the object instead of reclaiming it then this patchset fully support compaction. Its just that the kick methods are simplistic at this point.
Quoted 1 line · Christoph Lameter
Slab defragmentation is mainly an issue if Linux is used as a fileserver
Was hoping this would get renamed to SLUB Targetted Reclaim from discussions at VM Summit. As no copying is taking place, it's confusing to call it defragmentation to me anyway. Not a major deal but it made reading the patches a little confusing.
Quoted 7 lines
and large amounts of dentries, inodes and buffer heads accumulate. In some load situations the slabs become very sparsely populated so that a lot of memory is wasted by slabs that only contain one or a few objects. In extreme cases the performance of a machine will become sluggish since we are continually running reclaim. Slab defragmentation adds the capability to recover wasted memory.
When reading this first, I expected to find how slab objects get copied around and packed which is my problem with the defragmentation name. Again, not really that relevant to the code.
Quoted 6 lines
With lumpy reclaim slab defragmentation can be used to enhance the ability to recover larger contiguous areas of memory. Lumpy reclaim currently cannot do anything if a slab page is encountered. With slab defragmentation that slab page can be removed and a large contiguous page freed. It may be possible to have slab pages also part of
ZONE_MOVABLE(Mel's defrag scheme in 2.6.23)
More terminology nit-pick - ZONE_MOVABLE is not defragmenting anything. It's just partitioning memory. The slab pages need to be 100% reclaimable or movable for that to happen but even with targetted reclaim, some dentries such as the root directory one cannot be reclaimed, right?
Quoted 3 lines
or the MOVABLE areas (antifrag patches in mm).
It'd still be valid to leave them as MIGRATE_RECLAIMABLE because that is what they are. Arguably, MIGRATE_RECLAIMABLE could be dropped in it's entirety but I'd rather not as reclaimable blocks have significantly different reclaim costs to pages that are currently marked movable.
Quoted 29 lines
The patchset is also available via git
git pull
git://git.kernel.org/pub/scm/linux/kernel/git/christoph/slab.gitdefragCurrently memory reclaim from the following slab caches is possible:
1. dentry cache
2. inode cache (with a generic interface to allow easy setup of more filesystems than the currently supported ext2/3/4 reiserfs, XFS and proc)
3.buffer_headsOne typical mechanism that triggers slab defragmentation on my systems is the daily run of
updatedb
Updatedb scans all files on the system which causes a high inode and dentry use. After updatedb is complete we need to go back to the regular use patterns (typical on my machine: kernel compiles). Those need the memory now for different purposes. The inodes and dentries used for updatedb will gradually be aged by the dentry/inode reclaim algorithm which will free up the dentries and inode entries randomly through the slabs that were allocated. As a result the slabs will become sparsely populated. If they become empty then they can be freed but a lot of them will remain sparsely populated. That is where slab defrag comes in: It removes the slabs with just a few entries reclaiming more memory for other uses.
Quoted 6 lines
V5->V6
- Rediff against 2.6.24-rc2 + mm slub patches.
- Add reviewed by lines.
- Take out the experimental code to make slab pages movable. That has to wait until this has been considered by Mel.
I still haven't considered them properly. I've been backlogged for I don't know how long at this point and this is on the increasingly large todo list :( . I don't believe it is massively urgent at the moment though and reclaiming to start with is perfectly adequate just as lumpy reclaim is fine at the moment.
Quoted 18 lines
V4->V5:
- Support lumpy reclaim for slabs
- Support reclaim viaslab_shrink()
- Add constructors to insure a consistent object state at all times.
V3->V4:
- Optimize scan for slabs that need defragmentation
- Add/sys/slab/*/defrag_ratioto allow setting defrag limits per slab.
- Add support for buffer heads.
- Describe how the cleanup after the daily updatedb can be improved by slab defragmentation.
V2->V3
- Support directory reclaim
- Add infrastructure to trigger defragmentation after slab shrinking if we have slabs with a high degree of fragmentation.
Quoted 8 lines
V1->V2
- Clean up control flow using a state variable. Simplify API. Back to 2 functions that now take arrays of objects.
- Inode defrag support for a set of filesystems
- Fix up dentry defrag support to work on negative dentries by adding a new dentry flag that indicates that a dentry is not in the process of being freed or allocated.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Plans for Onezonelist patch series ???
Mel [anyone?]
Do you know what the plans are for your "onezonelist" patch series?
Are they going into -mm for, maybe, .25? Or have they been dropped.
I carry the last posting in my mempolicy tree--sometimes below my patches; sometimes above. Our patches touch some of the same places in mempolicy.c and require reject resolution when changing the order. I can save Andrew some work if I knew that your patches were going to be in the next -mm by holding off and doing the rebase myself.
Regards,
Lee
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Plans for Onezonelist patch series ???
Quoted 1 line · Lee Schermerhorn
Do you know what the plans are for your "onezonelist" patch series?
I wonder too whats going on? I thought they were ready for merging but I did not see a repost after the last round of comments.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Plans for Onezonelist patch series ???
On (08/11/07 10:34), Christoph Lameter didst pronounce:
Quoted 7 lines · Lee Schermerhorn
Quoted 2 lines
Do you know what the plans are for your "onezonelist" patch series?
I wonder too whats going on? I thought they were ready for merging but I did not see a repost after the last round of comments.
There was two bugs that were resolved but I didn't repost after that as mainline + -mm had gone to hell in a hand-basket and I didn't want to add to the mess.
Signature · 9 lines
Mel Gorman Part-time Phd Student Linux Technology Center University of Limerick IBM Dublin Software Lab -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Plans for Onezonelist patch series ???
Quoted 3 lines · Mel Gorman
There was two bugs that were resolved but I didn't repost after that as mainline + -mm had gone to hell in a hand-basket and I didn't want to add to the mess.
Hell? I must have missed it.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Plans for Onezonelist patch series ???
On (08/11/07 10:43), Christoph Lameter didst pronounce:
Quoted 8 lines · Mel Gorman
Quoted 4 lines
There was two bugs that were resolved but I didn't repost after that as mainline + -mm had gone to hell in a hand-basket and I didn't want to add to the mess.
Hell? I must have missed it.
Some time after rc1, things appeared in a mess - at least I didn't have much luck figuring out what was going on when I looked. Admittedly, being very ill at the time I didn't spend much effort on it. Either way things were churning enough that there seemed to be enough going on without adding one-zonelist to the mix.
I've rebased the patches to mm-broken-out-2007-11-06-02-32. However, the vanilla -mm and the one with onezonelist applied are locking up in the same manner. I'm way too behind at the moment to guess if it is a new bug or reported already. At best, I can say the patches are not making things any worse :) I'll go through the archives in the morning and do a bit more testing to see what happens.
In case this is familiar to people, the lockup I see is;
[ 115.548908] BUG: spinlock bad magic on CPU#0, sshd/2752 [ 115.611371] lock: c20029c8, .magic: ffffffff, .owner: <none>/-1, .owner_cpu: -1066669496 [ 115.709027] [<c010526a>] show_trace_log_lvl+0x1a/0x30 [ 115.770560] [<c0105c02>] show_trace+0x12/0x20 [ 115.823787] [<c0105d16>] dump_stack+0x16/0x20 [ 115.877011] [<c022c226>] spin_bug+0x96/0xf0 [ 115.928172] [<c022c429>] _raw_spin_lock+0x69/0x140 [ 115.986580] [<c033f05f>] _spin_lock+0x4f/0x60 [ 116.039809] [<c0224bae>] kobject_add+0x4e/0x1a0 [ 116.095112] [<c01314b4>] uids_user_create+0x54/0x80 [ 116.154555] [<c01318e2>] alloc_uid+0xd2/0x150 [ 116.207784] [<c01356db>] set_user+0x2b/0xb0 [ 116.258951] [<c01373c1>] sys_setreuid+0x141/0x150 [ 116.316305] [<c010429e>] syscall_call+0x7/0xb [ 116.369544] ======================= [ 127.680346] BUG: soft lockup - CPU#0 stuck for 11s! [sshd:2752] [ 127.750987] [ 127.768781] Pid: 2752, comm: sshd Not tainted (2.6.24-rc1-mm1 #1) [ 127.841498] EIP: 0060:[<c02298c1>] EFLAGS: 00000246 CPU: 0 [ 127.906948] EIP is at delay_tsc+0x1/0x20 [ 127.953754] EAX: 00000001 EBX: c20029c8 ECX: b0953e83 EDX: 2b35cb6d [ 128.028533] ESI: 04b81d83 EDI: 00000000 EBP: c30f1ec4 ESP: c30f1ebc [ 128.103305] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 [ 128.167717] CR0: 80050033 CR2: b7e45544 CR3: 02153000 CR4: 00000690 [ 128.242490] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 128.317253] DR6: ffff0ff0 DR7: 00000400 [ 128.363010] [<c010526a>] show_trace_log_lvl+0x1a/0x30 [ 128.424541] [<c0105c02>] show_trace+0x12/0x20 [ 128.477767] [<c010250c>] show_regs+0x1c/0x20 [ 128.529948] [<c015ab6b>] softlockup_tick+0x11b/0x150 [ 128.590446] [<c0130fb2>] run_local_timers+0x12/0x20 [ 128.649888] [<c0131182>] update_process_times+0x42/0x90 [ 128.713461] [<c01440f5>] tick_periodic+0x25/0x80 [ 128.769812] [<c0144169>] tick_handle_periodic+0x19/0x80 [ 128.833397] [<c0107519>] timer_interrupt+0x49/0x50 [ 128.891802] [<c015aeb8>] handle_IRQ_event+0x28/0x60 [ 128.951246] [<c015c7f8>] handle_level_irq+0x78/0xe0 [ 129.010693] [<c01065f0>] do_IRQ+0x40/0x80 [ 129.059782] [<c0104c5f>] common_interrupt+0x23/0x28 [ 129.119229] [<c022c472>] _raw_spin_lock+0xb2/0x140 [ 129.177635] [<c033f05f>] _spin_lock+0x4f/0x60 [ 129.230851] [<c0224bae>] kobject_add+0x4e/0x1a0 [ 129.286175] [<c01314b4>] uids_user_create+0x54/0x80 [ 129.345598] [<c01318e2>] alloc_uid+0xd2/0x150 [ 129.398830] [<c01356db>] set_user+0x2b/0xb0 [ 129.450005] [<c01373c1>] sys_setreuid+0x141/0x150 [ 129.507380] [<c010429e>] syscall_call+0x7/0xb [ 129.560605] =======================
Signature · 10 lines
-- Mel Gorman Part-time Phd Student Linux Technology Center University of Limerick IBM Dublin Software Lab -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Plans for Onezonelist patch series ???
Quoted 6 lines · Mel Gorman
I've rebased the patches to mm-broken-out-2007-11-06-02-32. However, the vanilla -mm and the one with onezonelist applied are locking up in the same manner. I'm way too behind at the moment to guess if it is a new bug or reported already. At best, I can say the patches are not making things any worse :) I'll go through the archives in the morning and do a bit more testing to see what happens.
I usually base my patches on Linus' tree as long as there is no tree available from Andrew. But that means that may have to approximate what is in there by adding this and that.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Plans for Onezonelist patch series ???
On (08/11/07 12:20), Christoph Lameter didst pronounce:
Quoted 9 lines · Mel Gorman
Quoted 7 lines
I've rebased the patches to mm-broken-out-2007-11-06-02-32. However, the vanilla -mm and the one with onezonelist applied are locking up in the same manner. I'm way too behind at the moment to guess if it is a new bug or reported already. At best, I can say the patches are not making things any worse :) I'll go through the archives in the morning and do a bit more testing to see what happens.
Quoted 4 lines
I usually base my patches on Linus' tree as long as there is no tree available from Andrew. But that means that may have to approximate what is in there by adding this and that.
Unfortunately for me, there are several collisions with the patches when applied against -mm if the patches are based on latest git. They are mainly in mm/vmscan.c due to the memory controller work. For the purposes of testing and merging, it makes more sense for me to work against -mm as much as possible.
Signature · 9 lines
Mel Gorman Part-time Phd Student Linux Technology Center University of Limerick IBM Dublin Software Lab -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Plans for Onezonelist patch series ???
In reply to Lee SchermerhornOn (08/11/07 11:01), Lee Schermerhorn didst pronounce:
Quoted 4 lines
Mel [anyone?]
Do you know what the plans are for your "onezonelist" patch series?
I was holding off trying to add new features to current mainline or -mm as there were a number of stability issues and one-zonelist touches a number of areas. Minimally, I was waiting for another -mm to come out and rebase to that. I'll rebase to latest git tomorrow, see how that looks and post it if passes regression tests on Monday.
Quoted 8 lines
Are they going into -mm for, maybe, .25? Or have they been dropped.
I carry the last posting in my mempolicy tree--sometimes below my patches; sometimes above. Our patches touch some of the same places in
mempolicy.cand require reject resolution when changing the order. I can save Andrew some work if I knew that your patches were going to be in the next -mm by holding off and doing the rebase myself.
The one-zonelist stuff is likely to be more controversial than what you are doing. It may be best if the one-zonelist patches are based on top of yours than the other way around.
Thanks
Signature · 9 lines
Mel Gorman Part-time Phd Student Linux Technology Center University of Limerick IBM Dublin Software Lab -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: Plans for Onezonelist patch series ???
Quoted 5 lines · Mel Gorman
I was holding off trying to add new features to current mainline or -mm as there were a number of stability issues and one-zonelist touches a number of areas. Minimally, I was waiting for another -mm to come out and rebase to that. I'll rebase to latest git tomorrow, see how that looks and post it if passes regression tests on Monday.
Ahh. Great. I am also impatiently waiting for that patchset. I was tempted several times this week to just pick up where you left off...
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 7 lines · Mel Gorman
Quoted 1 line · Christoph Lameter
Slab defragmentation is mainly an issue if Linux is used as a fileserver
Was hoping this would get renamed to SLUB Targetted Reclaim from discussions at VM Summit. As no copying is taking place, it's confusing to call it defragmentation to me anyway. Not a major deal but it made reading the patches a little confusing.
The problem is that people are focusing on one feature here and forget about the rest. Targetted reclaim is one feature that was added later when lumpy reclaim was added to the kernel. The primary intend of this patchset was always to reduce the fragmentation. The name is appropriate and the patchset will support copying of objects as soon as support for that is added to the kick(). In that case the copying you are looking for will be there. The simple implementation for the kick() methods is to simply copy pieces of the reclaim code. That is what is included here.
Quoted 7 lines
Quoted 6 lines
With lumpy reclaim slab defragmentation can be used to enhance the ability to recover larger contiguous areas of memory. Lumpy reclaim currently cannot do anything if a slab page is encountered. With slab defragmentation that slab page can be removed and a large contiguous page freed. It may be possible to have slab pages also part of
ZONE_MOVABLE(Mel's defrag scheme in 2.6.23)
Quoted 5 lines
More terminology nit-pick -
ZONE_MOVABLEis not defragmenting anything. It's just partitioning memory. The slab pages need to be 100% reclaimable or movable for that to happen but even with targetted reclaim, some dentries such as the root directory one cannot be reclaimed, right?
100%? I am so fond of these categorical statements ....
ZONE_MOVABLE also contains mlocked pages that are also not reclaimable. The question is at what level would it be possible to make them MOVABLE? It may take some improvements to the kick() methods to make eviction more reliable. Allowing the moving of objects in the kick() methods will likely get usthere.
Quoted 4 lines
It'd still be valid to leave them as
MIGRATE_RECLAIMABLEbecause that is what they are. Arguably,MIGRATE_RECLAIMABLEcould be dropped in it's entirety but I'd rather not as reclaimable blocks have significantly different reclaim costs to pages that are currently marked movable.
Right. That would simplify the antifrag methods. Is there any way to measure the reclaim costs?
Quoted 7 lines
Quoted 6 lines
V5->V6
- Rediff against 2.6.24-rc2 + mm slub patches.
- Add reviewed by lines.
- Take out the experimental code to make slab pages movable. That has to wait until this has been considered by Mel.
Quoted 5 lines
I still haven't considered them properly. I've been backlogged for I don't know how long at this point and this is on the increasingly large todo list :( . I don't believe it is massively urgent at the moment though and reclaiming to start with is perfectly adequate just as lumpy reclaim is fine at the moment.
Right. We can defer this for now.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
On (08/11/07 11:12), Christoph Lameter didst pronounce:
Quoted 10 lines · Mel Gorman
Quoted 8 lines · Christoph Lameter
Quoted 1 line
Slab defragmentation is mainly an issue if Linux is used as a fileserver
Was hoping this would get renamed to SLUB Targetted Reclaim from discussions at VM Summit. As no copying is taking place, it's confusing to call it defragmentation to me anyway. Not a major deal but it made reading the patches a little confusing.
Quoted 9 lines
The problem is that people are focusing on one feature here and forget about the rest. Targetted reclaim is one feature that was added later when lumpy reclaim was added to the kernel. The primary intend of this patchset was always to reduce the fragmentation. The name is appropriate and the patchset will support copying of objects as soon as support for that is added to the
kick(). In that case the copying you are looking for will be there. The simple implementation for thekick()methods is to simply copy pieces of the reclaim code. That is what is included here.
Ok, fair enough logic and it's a bit clearer in my head how to separate them out. Thanks
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
With lumpy reclaim slab defragmentation can be used to enhance the ability to recover larger contiguous areas of memory. Lumpy reclaim currently cannot do anything if a slab page is encountered. With slab defragmentation that slab page can be removed and a large contiguous page freed. It may be possible to have slab pages also part of
ZONE_MOVABLE(Mel's defrag scheme in 2.6.23)
Quoted 8 lines
Quoted 5 lines
More terminology nit-pick -
ZONE_MOVABLEis not defragmenting anything. It's just partitioning memory. The slab pages need to be 100% reclaimable or movable for that to happen but even with targetted reclaim, some dentries such as the root directory one cannot be reclaimed, right?100%? I am so fond of these categorical statements ....
Yeah, they are great for all occasions.
In fairness when the time comes, I can do a few tests using the hugepage allocation tests with ZONE_MOVABLE and Badari might do a few tests with memory hot-remove. Currently, the success rates for these tests are 100% within ZONE_MOVABLE although that is without locked pages. Hot-remove should be able to deal with locked pages but hugepage allocation wouldn't as lumpy-reclaim would fail. If we allow slab pages to use the zone and the success rates drop, it'll be obvious which is a plus at least.
Quoted 1 line
ZONE_MOVABLEalso contains mlocked pages that are also not reclaimable.
True, but they are movable so for example memory hot-remove is able to deal with them and the memory compaction patches should have been able to deal with it too.
Quoted 5 lines
The question is at what level would it be possible to make them MOVABLE? It may take some improvements to the
kick()methods to make eviction more reliable. Allowing the moving of objects in thekick()methods will likely get usthere.
It certainly can be tried out. However, this is a future problem and independent of the current patchset. I don't want to drag us down a blind alley about a problem that isn't even at hand.
Right now, I think the set looks in good shape for wider testing and appears to solve a major part of the slab fragmentation problem. Assuming I don't fall down a hole testing one-zonelist and the mm-broken-out patches, I'll get to testing these patches as well.
Quoted 8 lines
Quoted 4 lines
It'd still be valid to leave them as
MIGRATE_RECLAIMABLEbecause that is what they are. Arguably,MIGRATE_RECLAIMABLEcould be dropped in it's entirety but I'd rather not as reclaimable blocks have significantly different reclaim costs to pages that are currently marked movable.Right. That would simplify the antifrag methods. Is there any way to measure the reclaim costs?
Regrettably, no.
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
V5->V6
- Rediff against 2.6.24-rc2 + mm slub patches.
- Add reviewed by lines.
- Take out the experimental code to make slab pages movable. That has to wait until this has been considered by Mel.
Quoted 8 lines
Quoted 5 lines
I still haven't considered them properly. I've been backlogged for I don't know how long at this point and this is on the increasingly large todo list :( . I don't believe it is massively urgent at the moment though and reclaiming to start with is perfectly adequate just as lumpy reclaim is fine at the moment.
Right. We can defer this for now.
Agreed.
Signature · 9 lines
Mel Gorman Part-time Phd Student Linux Technology Center University of Limerick IBM Dublin Software Lab -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 3 lines · Mel Gorman
It certainly can be tried out. However, this is a future problem and independent of the current patchset. I don't want to drag us down a blind alley about a problem that isn't even at hand.
Right. That is why I took it out.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 32 lines · Christoph Lameter
Quoted 7 lines · Mel Gorman
Quoted 1 line · Christoph Lameter
Slab defragmentation is mainly an issue if Linux is used as a fileserver
Was hoping this would get renamed to SLUB Targetted Reclaim from discussions at VM Summit. As no copying is taking place, it's confusing to call it defragmentation to me anyway. Not a major deal but it made reading the patches a little confusing.
The problem is that people are focusing on one feature here and forget about the rest. Targetted reclaim is one feature that was added later when lumpy reclaim was added to the kernel. The primary intend of this patchset was always to reduce the fragmentation. The name is appropriate and the patchset will support copying of objects as soon as support for that is added to the
kick(). In that case the copying you are looking for will be there. The simple implementation for thekick()methods is to simply copy pieces of the reclaim code. That is what is included here.Quoted 7 lines
Quoted 6 lines
With lumpy reclaim slab defragmentation can be used to enhance the ability to recover larger contiguous areas of memory. Lumpy reclaim currently cannot do anything if a slab page is encountered. With slab defragmentation that slab page can be removed and a large contiguous page freed. It may be possible to have slab pages also part of
ZONE_MOVABLE(Mel's defrag scheme in 2.6.23)Quoted 5 lines
More terminology nit-pick -
ZONE_MOVABLEis not defragmenting anything. It's just partitioning memory. The slab pages need to be 100% reclaimable or movable for that to happen but even with targetted reclaim, some dentries such as the root directory one cannot be reclaimed, right?
Quoted 7 lines
100%? I am so fond of these categorical statements ....
ZONE_MOVABLEalso contains mlocked pages that are also not reclaimable. The question is at what level would it be possible to make them MOVABLE? It may take some improvements to thekick()methods to make eviction more reliable. Allowing the moving of objects in thekick()methods will likely get usthere.
Christoph: Although mlocked pages are not reclaimable, they ARE migratable. You fixed that a long time ago. [And I just verified with memtoy.] Doesn't this make them "movable"?
Lee
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 9 lines · Lee Schermerhorn
Quoted 5 lines
ZONE_MOVABLEalso contains mlocked pages that are also not reclaimable. The question is at what level would it be possible to make them MOVABLE? It may take some improvements to thekick()methods to make eviction more reliable. Allowing the moving of objects in thekick()methods will likely get usthere.Christoph: Although mlocked pages are not reclaimable, they ARE migratable. You fixed that a long time ago. [And I just verified with memtoy.] Doesn't this make them "movable"?
I know. They are movable but not reclaimable.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>