Zoned slab freeing In order to support zone reclaim we modify the shrinkers to be aware of the zone. Signed-off-by: Christoph Lameter Index: linux-2.6.16-rc1-mm1/fs/dquot.c =================================================================== --- linux-2.6.16-rc1-mm1.orig/fs/dquot.c 2006-01-18 13:42:05.000000000 -0800 +++ linux-2.6.16-rc1-mm1/fs/dquot.c 2006-01-19 14:11:43.000000000 -0800 @@ -480,7 +480,7 @@ int vfs_quota_sync(struct super_block *s } /* Free unused dquots from cache */ -static void prune_dqcache(int count) +static void prune_dqcache(int count, struct zone *z) { struct list_head *head; struct dquot *dquot; @@ -502,11 +502,11 @@ static void prune_dqcache(int count) * more memory */ -static int shrink_dqcache_memory(int nr, gfp_t gfp_mask) +static int shrink_dqcache_memory(int nr, gfp_t gfp_mask, struct zone *z) { if (nr) { spin_lock(&dq_list_lock); - prune_dqcache(nr); + prune_dqcache(nr, z); spin_unlock(&dq_list_lock); } return (dqstats.free_dquots / 100) * sysctl_vfs_cache_pressure; Index: linux-2.6.16-rc1-mm1/mm/vmscan.c =================================================================== --- linux-2.6.16-rc1-mm1.orig/mm/vmscan.c 2006-01-19 14:11:40.000000000 -0800 +++ linux-2.6.16-rc1-mm1/mm/vmscan.c 2006-01-19 14:11:43.000000000 -0800 @@ -178,7 +178,7 @@ EXPORT_SYMBOL(remove_shrinker); * * Returns the number of slab objects which we shrunk. */ -int shrink_slab(unsigned long scanned, gfp_t gfp_mask, unsigned long lru_pages) +int shrink_slab(unsigned long scanned, gfp_t gfp_mask, unsigned long lru_pages, struct zone *z) { struct shrinker *shrinker; int ret = 0; @@ -192,7 +192,7 @@ int shrink_slab(unsigned long scanned, g list_for_each_entry(shrinker, &shrinker_list, list) { unsigned long long delta; unsigned long total_scan; - unsigned long max_pass = (*shrinker->shrinker)(0, gfp_mask); + unsigned long max_pass = (*shrinker->shrinker)(0, gfp_mask, z); delta = (4 * scanned) / shrinker->seeks; delta *= max_pass; @@ -220,8 +220,8 @@ int shrink_slab(unsigned long scanned, g int shrink_ret; int nr_before; - nr_before = (*shrinker->shrinker)(0, gfp_mask); - shrink_ret = (*shrinker->shrinker)(this_scan, gfp_mask); + nr_before = (*shrinker->shrinker)(0, gfp_mask, NULL); + shrink_ret = (*shrinker->shrinker)(this_scan, gfp_mask, z); if (shrink_ret == -1) break; if (shrink_ret < nr_before) { @@ -1433,7 +1433,7 @@ int try_to_free_pages(struct zone **zone if (!priority) disable_swap_token(); shrink_caches(zones, &sc); - shrink_slab(sc.nr_scanned, gfp_mask, lru_pages); + shrink_slab(sc.nr_scanned, gfp_mask, lru_pages, NULL); if (reclaim_state) { sc.nr_reclaimed += reclaim_state->reclaimed_slab; reclaim_state->reclaimed_slab = 0; @@ -1602,7 +1602,7 @@ scan: atomic_dec(&zone->reclaim_in_progress); reclaim_state->reclaimed_slab = 0; nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL, - lru_pages); + lru_pages, NULL); sc.nr_reclaimed += reclaim_state->reclaimed_slab; total_reclaimed += sc.nr_reclaimed; total_scanned += sc.nr_scanned; @@ -1876,7 +1876,7 @@ int zone_reclaim(struct zone *zone, gfp_ if (zone_reclaim_mode & (RECLAIM_ZONE|RECLAIM_SWAP)) shrink_zone(zone, &sc); if (sc.nr_reclaimed < nr_pages && (zone_reclaim_mode & RECLAIM_SLAB)) - sc.nr_reclaimed = shrink_slab(sc.nr_scanned, gfp_mask, order); + sc.nr_reclaimed = shrink_slab(sc.nr_scanned, gfp_mask, order, zone); p->reclaim_state = NULL; current->flags &= ~PF_MEMALLOC; Index: linux-2.6.16-rc1-mm1/include/linux/mm.h =================================================================== --- linux-2.6.16-rc1-mm1.orig/include/linux/mm.h 2006-01-18 13:42:05.000000000 -0800 +++ linux-2.6.16-rc1-mm1/include/linux/mm.h 2006-01-19 14:11:43.000000000 -0800 @@ -780,8 +780,11 @@ extern unsigned long do_mremap(unsigned * * The callback will be passed nr_to_scan == 0 when the VM is querying the * cache size, so a fastpath for that case is appropriate. + * + * z will either be NULL for any zone or contain the zone to which + * the shrinking should be restricted. */ -typedef int (*shrinker_t)(int nr_to_scan, gfp_t gfp_mask); +typedef int (*shrinker_t)(int nr_to_scan, gfp_t gfp_mask, struct zone *z); /* * Add an aging callback. The int is the number of 'seeks' it takes @@ -1089,7 +1092,7 @@ int in_gate_area_no_task(unsigned long a int drop_caches_sysctl_handler(struct ctl_table *, int, struct file *, void __user *, size_t *, loff_t *); int 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.16-rc1-mm1/fs/inode.c =================================================================== --- linux-2.6.16-rc1-mm1.orig/fs/inode.c 2006-01-18 13:42:05.000000000 -0800 +++ linux-2.6.16-rc1-mm1/fs/inode.c 2006-01-19 14:11:43.000000000 -0800 @@ -416,7 +416,7 @@ static int can_unuse(struct inode *inode * If the inode has metadata buffers attached to mapping->private_list then * try to remove them. */ -static void prune_icache(int nr_to_scan) +static void prune_icache(int nr_to_scan, struct zone *z) { LIST_HEAD(freeable); int nr_pruned = 0; @@ -451,6 +451,8 @@ static void prune_icache(int nr_to_scan) if (!can_unuse(inode)) continue; } + if (z && z != virt_to_page(inode)) + continue; list_move(&inode->i_list, &freeable); inode->i_state |= I_FREEING; nr_pruned++; @@ -476,7 +478,7 @@ static void prune_icache(int nr_to_scan) * This function is passed the number of inodes to scan, and it returns the * total number of remaining possibly-reclaimable inodes. */ -static int shrink_icache_memory(int nr, gfp_t gfp_mask) +static int shrink_icache_memory(int nr, gfp_t gfp_mask, struct zone *z) { if (nr) { /* @@ -486,7 +488,7 @@ static int shrink_icache_memory(int nr, */ if (!(gfp_mask & __GFP_FS)) return -1; - prune_icache(nr); + prune_icache(nr, z); } return (inodes_stat.nr_unused / 100) * sysctl_vfs_cache_pressure; } Index: linux-2.6.16-rc1-mm1/fs/dcache.c =================================================================== --- linux-2.6.16-rc1-mm1.orig/fs/dcache.c 2006-01-18 13:42:05.000000000 -0800 +++ linux-2.6.16-rc1-mm1/fs/dcache.c 2006-01-19 14:11:45.000000000 -0800 @@ -494,7 +494,7 @@ static void prune_one_dentry(struct dent * all the dentries are in use. */ -static void prune_dcache(int count) +static void prune_dcache(int count, struct zone *z) { spin_lock(&dcache_lock); for (; count ; count--) { @@ -529,6 +529,8 @@ static void prune_dcache(int count) spin_unlock(&dentry->d_lock); continue; } + if (z && z != page_zone(virt_to_page(dentry))) + continue; prune_one_dentry(dentry); } spin_unlock(&dcache_lock); @@ -762,7 +764,7 @@ void shrink_dcache_parent(struct dentry found: spin_unlock(&dcache_lock); - prune_dcache(found); + prune_dcache(found, NULL); } spin_unlock(&dcache_lock); } @@ -836,7 +838,7 @@ void shrink_dcache_anon(struct super_blo found: spin_unlock(&dcache_lock); - prune_dcache(found); + prune_dcache(found, NULL); } spin_unlock(&dcache_lock); } @@ -853,12 +855,12 @@ found: * * In this case we return -1 to tell the caller that we baled. */ -static int shrink_dcache_memory(int nr, gfp_t gfp_mask) +static int shrink_dcache_memory(int nr, gfp_t gfp_mask, struct zone *z) { if (nr) { if (!(gfp_mask & __GFP_FS)) return -1; - prune_dcache(nr); + prune_dcache(nr, z); } return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure; } Index: linux-2.6.16-rc1-mm1/fs/mbcache.c =================================================================== --- linux-2.6.16-rc1-mm1.orig/fs/mbcache.c 2006-01-18 13:42:05.000000000 -0800 +++ linux-2.6.16-rc1-mm1/fs/mbcache.c 2006-01-19 14:11:43.000000000 -0800 @@ -116,7 +116,7 @@ mb_cache_indexes(struct mb_cache *cache) * What the mbcache registers as to get shrunk dynamically. */ -static int mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask); +static int mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask, struct zone *z); static inline int @@ -193,7 +193,7 @@ forget: * Returns the number of objects which are present in the cache. */ static int -mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask) +mb_cache_shrink_fn(int nr_to_scan, gfp_t gfp_mask, struct zone *z) { LIST_HEAD(free_list); struct list_head *l, *ltmp; Index: linux-2.6.16-rc1-mm1/kernel/sysctl.c =================================================================== --- linux-2.6.16-rc1-mm1.orig/kernel/sysctl.c 2006-01-19 11:18:41.000000000 -0800 +++ linux-2.6.16-rc1-mm1/kernel/sysctl.c 2006-01-19 14:11:43.000000000 -0800 @@ -886,7 +886,8 @@ static ctl_table vm_table[] = { .maxlen = sizeof(zone_reclaim_mode), .mode = 0644, .proc_handler = &proc_dointvec, - .strategy = &zero, + .strategy = &sysctl_intvec, + .extra1 = &zero, }, { .ctl_name = VM_ZONE_RECLAIM_INTERVAL, @@ -895,7 +896,8 @@ static ctl_table vm_table[] = { .maxlen = sizeof(zone_reclaim_interval), .mode = 0644, .proc_handler = &proc_dointvec, - .strategy = &zero, + .strategy = &sysctl_intvec, + .extra1 = &zero, }, #endif { .ctl_name = 0 } Index: linux-2.6.16-rc1-mm1/mm/mempolicy.c =================================================================== --- linux-2.6.16-rc1-mm1.orig/mm/mempolicy.c 2006-01-18 13:41:50.000000000 -0800 +++ linux-2.6.16-rc1-mm1/mm/mempolicy.c 2006-01-19 14:11:45.000000000 -0800 @@ -543,7 +543,6 @@ static void migrate_page_add(struct page if ((flags & MPOL_MF_MOVE_ALL) || page_mapcount(page) ==1) if (isolate_lru_page(page)) list_add(&page->lru, pagelist); - } } /* Index: linux-2.6.16-rc1-mm1/fs/drop_caches.c =================================================================== --- linux-2.6.16-rc1-mm1.orig/fs/drop_caches.c 2006-01-16 23:44:47.000000000 -0800 +++ linux-2.6.16-rc1-mm1/fs/drop_caches.c 2006-01-19 14:11:45.000000000 -0800 @@ -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); }