--- fs/inode.c | 43 +++++++++++++++++++++++++++++++++---------- fs/proc/inode.c | 15 +++++++++++++-- fs/reiserfs/super.c | 13 ++++++++++++- fs/xfs/linux-2.6/kmem.h | 5 +++-- fs/xfs/linux-2.6/xfs_buf.c | 2 +- fs/xfs/linux-2.6/xfs_super.c | 13 ++++++++++++- include/linux/fs.h | 7 +++++-- mm/shmem.c | 13 ++++++++++++- net/socket.c | 13 ++++++++++++- 9 files changed, 103 insertions(+), 21 deletions(-) Index: slub/fs/inode.c =================================================================== --- slub.orig/fs/inode.c 2007-05-17 20:46:05.000000000 -0700 +++ slub/fs/inode.c 2007-05-18 00:13:15.000000000 -0700 @@ -1364,30 +1364,52 @@ __setup("ihash_entries=", set_ihash_entr static void *get_inodes(struct kmem_cache *s, int nr, void **v) { int i; - unsigned long abort = 0; spin_lock(&inode_lock); for (i = 0; i < nr; i++) { struct inode *inode = v[i]; - if (abort || (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE))) + if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) v[i] = NULL; - else { + else __iget(inode); - abort = atomic_read(&inode->i_count) > 1; - } } spin_unlock(&inode_lock); - return (void *)abort; + return NULL; +} + +/* + * Function for filesystems that embedd struct inode into their own + * structures. + */ +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); -static void kick_inodes(struct kmem_cache *s, int nr, void **v, void *private) +void kick_inodes(struct kmem_cache *s, int nr, void **v, void *private) { struct inode *inode; int i; - unsigned long abort = (unsigned long)private; + int abort = 0; LIST_HEAD(freeable); + /* Remove possible dentry references to the inodes */ + for (i = 0; i < nr; i++) { + inode = v[i]; + if (!inode) + continue; + + if (atomic_read(&inode->i_count) > 1) + d_prune_aliases(inode); + } + mutex_lock(&iprune_mutex); spin_lock(&inode_lock); for (i = 0; i < nr; i++) { @@ -1396,7 +1418,7 @@ static void kick_inodes(struct kmem_cach continue; if (abort || inode->i_state || atomic_read(&inode->i_count) > 1) { - /* Inode in use ! */ + /* Inode in use */ iput(inode); abort = 1; continue; @@ -1424,8 +1446,9 @@ static void kick_inodes(struct kmem_cach dispose_list(&freeable); mutex_unlock(&iprune_mutex); } +EXPORT_SYMBOL(kick_inodes); -struct kmem_cache_ops inode_kmem_cache_ops = { +static struct kmem_cache_ops inode_kmem_cache_ops = { .get = get_inodes, .kick = kick_inodes }; Index: slub/fs/reiserfs/super.c =================================================================== --- slub.orig/fs/reiserfs/super.c 2007-05-17 20:38:23.000000000 -0700 +++ slub/fs/reiserfs/super.c 2007-05-17 22:27:41.000000000 -0700 @@ -520,6 +520,16 @@ static void init_once(void *foo, struct #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)); +} + +struct kmem_cache_ops reiserfs_kmem_cache_ops = { + .get = reiserfs_get_inodes, + .kick = kick_inodes +}; + static int init_inodecache(void) { reiserfs_inode_cachep = kmem_cache_create("reiser_inode_cache", @@ -527,7 +537,8 @@ static int init_inodecache(void) reiserfs_inode_info), 0, (SLAB_RECLAIM_ACCOUNT| SLAB_MEM_SPREAD), - init_once, NULL); + init_once, + &reiserfs_kmem_cache_ops); if (reiserfs_inode_cachep == NULL) return -ENOMEM; return 0; Index: slub/fs/xfs/linux-2.6/kmem.h =================================================================== --- slub.orig/fs/xfs/linux-2.6/kmem.h 2007-05-17 20:41:13.000000000 -0700 +++ slub/fs/xfs/linux-2.6/kmem.h 2007-05-17 22:13:41.000000000 -0700 @@ -79,9 +79,10 @@ kmem_zone_init(int size, char *zone_name static inline kmem_zone_t * kmem_zone_init_flags(int size, char *zone_name, unsigned long flags, - void (*construct)(void *, kmem_zone_t *, unsigned long)) + void (*construct)(void *, kmem_zone_t *, unsigned long), + const struct kmem_cache_ops *ops) { - return kmem_cache_create(zone_name, size, 0, flags, construct, NULL); + return kmem_cache_create(zone_name, size, 0, flags, construct, ops); } static inline void Index: slub/fs/xfs/linux-2.6/xfs_buf.c =================================================================== --- slub.orig/fs/xfs/linux-2.6/xfs_buf.c 2007-05-17 20:42:51.000000000 -0700 +++ slub/fs/xfs/linux-2.6/xfs_buf.c 2007-05-17 20:43:04.000000000 -0700 @@ -1832,7 +1832,7 @@ xfs_buf_init(void) #endif xfs_buf_zone = kmem_zone_init_flags(sizeof(xfs_buf_t), "xfs_buf", - KM_ZONE_HWALIGN, NULL); + KM_ZONE_HWALIGN, NULL, NULL); if (!xfs_buf_zone) goto out_free_trace_buf; Index: slub/fs/xfs/linux-2.6/xfs_super.c =================================================================== --- slub.orig/fs/xfs/linux-2.6/xfs_super.c 2007-05-17 20:39:39.000000000 -0700 +++ slub/fs/xfs/linux-2.6/xfs_super.c 2007-05-17 22:15:40.000000000 -0700 @@ -355,13 +355,24 @@ xfs_fs_inode_init_once( inode_init_once(vn_to_inode((bhv_vnode_t *)vnode)); } +static void *xfs_get_inodes(struct kmem_cache *s, int nr, void **v) +{ + return fs_get_inodes(s, nr, v, offsetof(bhv_vnode_t, v_inode)); +}; + +static struct kmem_cache_ops xfs_kmem_cache_ops = { + .get = xfs_get_inodes, + .kick = kick_inodes +}; + STATIC int xfs_init_zones(void) { xfs_vnode_zone = kmem_zone_init_flags(sizeof(bhv_vnode_t), "xfs_vnode", KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | KM_ZONE_SPREAD, - xfs_fs_inode_init_once); + xfs_fs_inode_init_once, + &xfs_kmem_cache_ops); if (!xfs_vnode_zone) goto out; Index: slub/include/linux/fs.h =================================================================== --- slub.orig/include/linux/fs.h 2007-05-17 20:46:33.000000000 -0700 +++ slub/include/linux/fs.h 2007-05-17 22:21:09.000000000 -0700 @@ -1602,14 +1602,17 @@ extern int __remove_suid(struct dentry * extern int should_remove_suid(struct dentry *); extern int remove_suid(struct dentry *); -extern struct inode_kmem_cache_ops; - extern void __insert_inode_hash(struct inode *, unsigned long hashval); extern void remove_inode_hash(struct inode *); static inline void insert_inode_hash(struct inode *inode) { __insert_inode_hash(inode, inode->i_ino); } +/* Inode defrag support */ +extern void kick_inodes(struct kmem_cache *, int, void **, 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); Index: slub/fs/proc/inode.c =================================================================== --- slub.orig/fs/proc/inode.c 2007-05-17 20:52:02.000000000 -0700 +++ slub/fs/proc/inode.c 2007-05-17 22:27:06.000000000 -0700 @@ -111,14 +111,25 @@ static void init_once(void * foo, struct inode_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)); +}; + +static struct kmem_cache_ops proc_kmem_cache_ops = { + .get = proc_get_inodes, + .kick = kick_inodes +}; + int __init proc_init_inodecache(void) { proc_inode_cachep = kmem_cache_create("proc_inode_cache", sizeof(struct proc_inode), 0, (SLAB_RECLAIM_ACCOUNT| SLAB_MEM_SPREAD), - init_once, NULL); + init_once, &proc_kmem_cache_ops); if (proc_inode_cachep == NULL) return -ENOMEM; return 0; Index: slub/mm/shmem.c =================================================================== --- slub.orig/mm/shmem.c 2007-05-17 22:27:18.000000000 -0700 +++ slub/mm/shmem.c 2007-05-17 22:29:34.000000000 -0700 @@ -2337,11 +2337,22 @@ static void init_once(void *foo, struct #endif } +static void *shmem_get_inodes(struct kmem_cache *s, int nr, void **v) +{ + return fs_get_inodes(s, nr, v, + offsetof(struct shmem_inode_info, vfs_inode)); +} + +static struct kmem_cache_ops shmem_kmem_cache_ops = { + .get = shmem_get_inodes, + .kick = kick_inodes +}; + static int init_inodecache(void) { shmem_inode_cachep = kmem_cache_create("shmem_inode_cache", sizeof(struct shmem_inode_info), - 0, 0, init_once, NULL); + 0, 0, init_once, &shmem_kmem_cache_ops); if (shmem_inode_cachep == NULL) return -ENOMEM; return 0; Index: slub/net/socket.c =================================================================== --- slub.orig/net/socket.c 2007-05-17 22:24:51.000000000 -0700 +++ slub/net/socket.c 2007-05-17 22:26:52.000000000 -0700 @@ -264,6 +264,17 @@ static void init_once(void *foo, struct inode_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 struct kmem_cache_ops sock_kmem_cache_ops = { + .get = sock_get_inodes, + .kick = kick_inodes +}; + static int init_inodecache(void) { sock_inode_cachep = kmem_cache_create("sock_inode_cache", @@ -273,7 +284,7 @@ static int init_inodecache(void) SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD), init_once, - NULL); + &sock_kmem_cache_ops); if (sock_inode_cachep == NULL) return -ENOMEM; return 0;