diff -urN 2.3.42/fs/dcache.c 2.3.42-idcache/fs/dcache.c --- 2.3.42/fs/dcache.c Sun Jan 30 15:43:39 2000 +++ 2.3.42-idcache/fs/dcache.c Tue Feb 8 12:26:43 2000 @@ -57,6 +57,15 @@ int dummy[2]; } dentry_stat = {0, 0, 45, 0,}; +struct { + /* Enlarging too much is not a good idea since a too large cache + may generate too much collisions in the hash potentially + slowing down the system. */ + int limit_percent; +} dcache_ctl = { 2, }; +int dcache_ctl_min[] = { 0, }; +int dcache_ctl_max[] = { 100, }; + static inline void d_free(struct dentry *dentry) { if (dentry->d_op && dentry->d_op->d_release) @@ -428,6 +437,20 @@ return 0; } +static inline void preshrink_dcache_memory(void) +{ + unsigned long size, limit; + + size = (dentry_stat.nr_unused * sizeof(struct dentry)) >> PAGE_SHIFT; + limit = num_physpages * dcache_ctl.limit_percent / 100; + if (size > limit) + { + lock_kernel(); + prune_dcache(dentry_stat.nr_unused >> 2); + unlock_kernel(); + } +} + #define NAME_ALLOC_LEN(len) ((len+16) & ~15) struct dentry * d_alloc(struct dentry * parent, const struct qstr *name) @@ -435,6 +458,7 @@ char * str; struct dentry *dentry; + preshrink_dcache_memory(); dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL); if (!dentry) return NULL; diff -urN 2.3.42/fs/inode.c 2.3.42-idcache/fs/inode.c --- 2.3.42/fs/inode.c Sun Jan 30 15:43:39 2000 +++ 2.3.42-idcache/fs/inode.c Tue Feb 8 12:26:43 2000 @@ -70,10 +70,19 @@ int dummy[5]; } inodes_stat = {0, 0,}; +struct { + /* Enlarging too much is not a good idea since a too large cache + may generate too much collisions in the hash potentially + slowing down the system. */ + int limit_percent; +} icache_ctl = { 2, }; +int icache_ctl_min[] = { 0, }; +int icache_ctl_max[] = { 100, }; + static kmem_cache_t * inode_cachep; #define alloc_inode() \ - ((struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL)) + (preshrink_icache_memory(), (struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL)) #define destroy_inode(inode) kmem_cache_free(inode_cachep, (inode)) /* @@ -411,6 +420,16 @@ kmem_cache_shrink(inode_cachep); return 0; +} + +static inline void preshrink_icache_memory(void) +{ + unsigned long size, limit; + + size = (inodes_stat.nr_unused * sizeof(struct inode)) >> PAGE_SHIFT; + limit = num_physpages * icache_ctl.limit_percent / 100; + if (size > limit) + prune_icache(inodes_stat.nr_unused >> 2); } static inline void __iget(struct inode * inode) diff -urN 2.3.42/include/linux/sysctl.h 2.3.42-idcache/include/linux/sysctl.h --- 2.3.42/include/linux/sysctl.h Sun Jan 30 15:43:39 2000 +++ 2.3.42-idcache/include/linux/sysctl.h Tue Feb 8 12:26:43 2000 @@ -500,7 +500,9 @@ FS_NRSUPER=9, /* int:current number of allocated super_blocks */ FS_MAXSUPER=10, /* int:maximum number of super_blocks that can be allocated */ FS_OVERFLOWUID=11, /* int: overflow UID */ - FS_OVERFLOWGID=12 /* int: overflow GID */ + FS_OVERFLOWGID=12, /* int: overflow GID */ + FS_DCACHE_CTL=13, /* dentry cache controls */ + FS_ICACHE_CTL=14, /* inode cache controls */ }; /* CTL_DEBUG names: */ diff -urN 2.3.42/kernel/sysctl.c 2.3.42-idcache/kernel/sysctl.c --- 2.3.42/kernel/sysctl.c Sun Jan 30 15:43:40 2000 +++ 2.3.42-idcache/kernel/sysctl.c Tue Feb 8 12:26:43 2000 @@ -47,6 +47,9 @@ static int maxolduid = 65535; static int minolduid = 0; +extern int dcache_ctl[], dcache_ctl_min[], dcache_ctl_max[]; +extern int icache_ctl[], icache_ctl_min[], icache_ctl_max[]; + #ifdef CONFIG_KMOD extern char modprobe_path[]; #endif @@ -306,6 +309,12 @@ {FS_OVERFLOWGID, "overflowgid", &fs_overflowgid, sizeof(int), 0644, NULL, &proc_dointvec_minmax, &sysctl_intvec, NULL, &minolduid, &maxolduid}, + {FS_DCACHE_CTL, "dcache_ctl", &dcache_ctl, 1*sizeof(int), 0644, NULL, + &proc_dointvec_minmax, &sysctl_intvec, NULL, + &dcache_ctl_min, &dcache_ctl_max}, + {FS_ICACHE_CTL, "icache_ctl", &icache_ctl, 1*sizeof(int), 0644, NULL, + &proc_dointvec_minmax, &sysctl_intvec, NULL, + &icache_ctl_min, &icache_ctl_max}, {0} };