From: Chris Wright sysfs_new_dirent() should be using a standalone slab cache for allocating sysfs_dirent instances. That way, we use 36 bytes for each one rather than 64. Without, size-64 looks like so: size-64 4064 4108 76 52 1 : tunables 32 16 8 : slabdata 79 79 0 : globalstat 4263 4079 79 0 0 0 84 0 : cpustat 15986 337 12286 3 And with: size-64 1196 1196 76 52 1 : tunables 32 16 8 : slabdata 23 23 0 : globalstat 1297 1196 23 0 0 0 84 0 : cpustat 12418 108 11349 1 sysfs_dir_cache 2862 2916 48 81 1 : tunables 32 16 8 : slabdata 36 36 0 : globalstat 2931 2874 36 0 0 0 113 0 : cpustat 2756 216 110 0 Signed-off-by: Chris Wright Signed-off-by: Andrew Morton --- 25-akpm/fs/sysfs/dir.c | 2 +- 25-akpm/fs/sysfs/mount.c | 17 +++++++++++++++-- 25-akpm/fs/sysfs/sysfs.h | 3 ++- 3 files changed, 18 insertions(+), 4 deletions(-) diff -puN fs/sysfs/dir.c~allocate-sysfs_dirent-structures-from-their-own-slab fs/sysfs/dir.c --- 25/fs/sysfs/dir.c~allocate-sysfs_dirent-structures-from-their-own-slab 2004-12-03 20:56:01.279565664 -0800 +++ 25-akpm/fs/sysfs/dir.c 2004-12-03 20:56:01.286564600 -0800 @@ -36,7 +36,7 @@ static struct sysfs_dirent * sysfs_new_d { struct sysfs_dirent * sd; - sd = kmalloc(sizeof(*sd), GFP_KERNEL); + sd = kmem_cache_alloc(sysfs_dir_cachep, GFP_KERNEL); if (!sd) return NULL; diff -puN fs/sysfs/mount.c~allocate-sysfs_dirent-structures-from-their-own-slab fs/sysfs/mount.c --- 25/fs/sysfs/mount.c~allocate-sysfs_dirent-structures-from-their-own-slab 2004-12-03 20:56:01.281565360 -0800 +++ 25-akpm/fs/sysfs/mount.c 2004-12-03 20:56:01.286564600 -0800 @@ -16,6 +16,7 @@ struct vfsmount *sysfs_mount; struct super_block * sysfs_sb = NULL; +kmem_cache_t *sysfs_dir_cachep; static struct super_operations sysfs_ops = { .statfs = simple_statfs, @@ -77,7 +78,13 @@ static struct file_system_type sysfs_fs_ int __init sysfs_init(void) { - int err; + int err = -ENOMEM; + + sysfs_dir_cachep = kmem_cache_create("sysfs_dir_cache", + sizeof(struct sysfs_dirent), + 0, 0, NULL, NULL); + if (!sysfs_dir_cachep) + goto out; err = register_filesystem(&sysfs_fs_type); if (!err) { @@ -86,7 +93,13 @@ int __init sysfs_init(void) printk(KERN_ERR "sysfs: could not mount!\n"); err = PTR_ERR(sysfs_mount); sysfs_mount = NULL; + goto out_err; } - } + } else + goto out_err; +out: return err; +out_err: + kmem_cache_destroy(sysfs_dir_cachep); + goto out; } diff -puN fs/sysfs/sysfs.h~allocate-sysfs_dirent-structures-from-their-own-slab fs/sysfs/sysfs.h --- 25/fs/sysfs/sysfs.h~allocate-sysfs_dirent-structures-from-their-own-slab 2004-12-03 20:56:01.282565208 -0800 +++ 25-akpm/fs/sysfs/sysfs.h 2004-12-03 20:56:01.287564448 -0800 @@ -1,5 +1,6 @@ extern struct vfsmount * sysfs_mount; +extern kmem_cache_t *sysfs_dir_cachep; extern struct inode * sysfs_new_inode(mode_t mode); extern int sysfs_create(struct dentry *, int mode, int (*init)(struct inode *)); @@ -74,7 +75,7 @@ static inline void release_sysfs_dirent( kobject_put(sl->target_kobj); kfree(sl); } - kfree(sd); + kmem_cache_free(sysfs_dir_cachep, sd); } static inline struct sysfs_dirent * sysfs_get(struct sysfs_dirent * sd) _