[PATCH]

* struct file cleanup : the very large file_ra_state is now allocated only on demand, 
using a dedicated "filp_ra_cache" slab.
    machines handling lot of sockets or pipes can save about 80 bytes (or 40 
bytes on 32bits platforms) per file.

* private_data : The field is moved close to f_count and f_op fields to speedup 
sockfd_lookups

Thank you

Signed-off-by: Eric Dumazet <[EMAIL PROTECTED]>

--- linux-2.6.13-rc6/include/linux/fs.h 2005-08-07 20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/include/linux/fs.h      2005-08-18 10:30:35.000000000 
+0200
@@ -586,20 +586,18 @@
        struct dentry           *f_dentry;
        struct vfsmount         *f_vfsmnt;
        struct file_operations  *f_op;
+       void                    *private_data;
        atomic_t                f_count;
        unsigned int            f_flags;
        mode_t                  f_mode;
        loff_t                  f_pos;
        struct fown_struct      f_owner;
        unsigned int            f_uid, f_gid;
-       struct file_ra_state    f_ra;
 
        size_t                  f_maxcount;
        unsigned long           f_version;
        void                    *f_security;
 
-       /* needed for tty driver, and maybe others */
-       void                    *private_data;
 
 #ifdef CONFIG_EPOLL
        /* Used by fs/eventpoll.c to link all the hooks to this file */
@@ -1480,7 +1478,10 @@
        __insert_inode_hash(inode, inode->i_ino);
 }
 
-extern struct file * get_empty_filp(void);
+#define FILP_NO_READ_AHEAD   0
+#define FILP_WITH_READ_AHEAD 1
+extern struct file * get_empty_filp(int need_read_ahead);
+
 extern void file_move(struct file *f, struct list_head *list);
 extern void file_kill(struct file *f);
 struct bio;
@@ -1514,8 +1515,7 @@
 extern void do_generic_mapping_read(struct address_space *mapping,
                                    struct file_ra_state *, struct file *,
                                    loff_t *, read_descriptor_t *, 
read_actor_t);
-extern void
-file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping);
+extern void file_ra_state_init(struct file *);
 extern ssize_t generic_file_direct_IO(int rw, struct kiocb *iocb,
        const struct iovec *iov, loff_t offset, unsigned long nr_segs);
 extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov, 
@@ -1545,12 +1545,16 @@
 }
 #endif
 
+static inline struct file_ra_state *get_ra_state(struct file *f)
+{
+       return (struct file_ra_state *)(f+1);
+}
 static inline void do_generic_file_read(struct file * filp, loff_t *ppos,
                                        read_descriptor_t * desc,
                                        read_actor_t actor)
 {
        do_generic_mapping_read(filp->f_mapping,
-                               &filp->f_ra,
+                               get_ra_state(filp),
                                filp,
                                ppos,
                                desc,
--- linux-2.6.13-rc6/include/linux/slab.h       2005-08-07 20:18:56.000000000 
+0200
+++ linux-2.6.13-rc6-ed/include/linux/slab.h    2005-08-18 09:46:40.000000000 
+0200
@@ -125,6 +125,7 @@
 extern kmem_cache_t    *names_cachep;
 extern kmem_cache_t    *files_cachep;
 extern kmem_cache_t    *filp_cachep;
+extern kmem_cache_t    *filp_ra_cachep;
 extern kmem_cache_t    *fs_cachep;
 extern kmem_cache_t    *signal_cachep;
 extern kmem_cache_t    *sighand_cachep;
--- linux-2.6.13-rc6/mm/readahead.c     2005-08-07 20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/mm/readahead.c  2005-08-18 10:41:13.000000000 +0200
@@ -33,9 +33,10 @@
  * memset *ra to zero.
  */
 void
-file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping)
+file_ra_state_init(struct file *file)
 {
-       ra->ra_pages = mapping->backing_dev_info->ra_pages;
+       struct file_ra_state *ra = get_ra_state(file);
+       ra->ra_pages = 
file->f_mapping->host->i_mapping->backing_dev_info->ra_pages;
        ra->prev_page = -1;
 }
 
--- linux-2.6.13-rc6/mm/filemap.c       2005-08-07 20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/mm/filemap.c    2005-08-18 10:46:53.000000000 +0200
@@ -1187,7 +1187,7 @@
        int error;
        struct file *file = area->vm_file;
        struct address_space *mapping = file->f_mapping;
-       struct file_ra_state *ra = &file->f_ra;
+       struct file_ra_state *ra = get_ra_state(file);
        struct inode *inode = mapping->host;
        struct page *page;
        unsigned long size, pgoff;
@@ -1243,7 +1243,7 @@
                        inc_page_state(pgmajfault);
                }
                did_readaround = 1;
-               ra_pages = max_sane_readahead(file->f_ra.ra_pages);
+               ra_pages = max_sane_readahead(ra->ra_pages);
                if (ra_pages) {
                        pgoff_t start = 0;
 
--- linux-2.6.13-rc6/mm/fadvise.c       2005-08-07 20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/mm/fadvise.c    2005-08-18 10:44:16.000000000 +0200
@@ -28,6 +28,7 @@
        struct file *file = fget(fd);
        struct address_space *mapping;
        struct backing_dev_info *bdi;
+       struct file_ra_state *ra;
        loff_t endbyte;
        pgoff_t start_index;
        pgoff_t end_index;
@@ -54,15 +55,20 @@
 
        bdi = mapping->backing_dev_info;
 
+       /*
+        * FIXME : Are we sure here this 'file' has ra_state available ?
+        */
+       ra = get_ra_state(file);
+
        switch (advice) {
        case POSIX_FADV_NORMAL:
-               file->f_ra.ra_pages = bdi->ra_pages;
+               ra->ra_pages = bdi->ra_pages;
                break;
        case POSIX_FADV_RANDOM:
-               file->f_ra.ra_pages = 0;
+               ra->ra_pages = 0;
                break;
        case POSIX_FADV_SEQUENTIAL:
-               file->f_ra.ra_pages = bdi->ra_pages * 2;
+               ra->ra_pages = bdi->ra_pages * 2;
                break;
        case POSIX_FADV_WILLNEED:
        case POSIX_FADV_NOREUSE:
--- linux-2.6.13-rc6/fs/file_table.c    2005-08-07 20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/fs/file_table.c 2005-08-18 10:46:53.000000000 +0200
@@ -53,16 +53,20 @@
        spin_unlock_irqrestore(&filp_count_lock, flags);
 }
 
+/*
+ * a file can belong to different kmem_cache (filp_cache or filp_ra_cache),
+ * so let kfree() find it
+ */
 static inline void file_free(struct file *f)
 {
-       kmem_cache_free(filp_cachep, f);
+       kfree(f);
 }
 
 /* Find an unused file structure and return a pointer to it.
  * Returns NULL, if there are no more free file structures or
  * we run out of memory.
  */
-struct file *get_empty_filp(void)
+struct file *get_empty_filp(int need_read_ahead)
 {
        static int old_max;
        struct file * f;
@@ -74,11 +78,11 @@
                                !capable(CAP_SYS_ADMIN))
                goto over;
 
-       f = kmem_cache_alloc(filp_cachep, GFP_KERNEL);
+       f = kmem_cache_alloc(need_read_ahead ? filp_ra_cachep : filp_cachep, 
GFP_KERNEL);
        if (f == NULL)
                goto fail;
 
-       memset(f, 0, sizeof(*f));
+       memset(f, 0, need_read_ahead ? sizeof(struct file) + sizeof(struct 
file_ra_state) : sizeof(struct file));
        if (security_file_alloc(f))
                goto fail_sec;
 
--- linux-2.6.13-rc6/fs/open.c  2005-08-07 20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/fs/open.c       2005-08-18 10:30:35.000000000 +0200
@@ -778,7 +778,7 @@
        int error;
 
        error = -ENFILE;
-       f = get_empty_filp();
+       f = get_empty_filp(FILP_WITH_READ_AHEAD);
        if (!f)
                goto cleanup_dentry;
        f->f_flags = flags;
@@ -804,7 +804,7 @@
        }
        f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 
-       file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
+       file_ra_state_init(f);
 
        /* NB: we're sure to have correct a_ops only after f_op->open */
        if (f->f_flags & O_DIRECT) {
--- linux-2.6.13-rc6/fs/dcache.c        2005-08-07 20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/fs/dcache.c     2005-08-18 09:48:41.000000000 +0200
@@ -1703,8 +1703,10 @@
 /* SLAB cache for __getname() consumers */
 kmem_cache_t *names_cachep;
 
-/* SLAB cache for file structures */
+/* SLAB cache for file structures without read ahead state data */
 kmem_cache_t *filp_cachep;
+/* SLAB cache for file structures with read ahead state data */
+kmem_cache_t *filp_ra_cachep;
 
 EXPORT_SYMBOL(d_genocide);
 
@@ -1733,6 +1735,9 @@
        filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
                        SLAB_HWCACHE_ALIGN|SLAB_PANIC, filp_ctor, filp_dtor);
 
+       filp_ra_cachep = kmem_cache_create("filp_ra", sizeof(struct file) + 
sizeof(struct file_ra_state), 0,
+                       SLAB_HWCACHE_ALIGN|SLAB_PANIC, filp_ctor, filp_dtor);
+
        dcache_init(mempages);
        inode_init(mempages);
        files_init(mempages);
--- linux-2.6.13-rc6/net/socket.c       2005-08-07 20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/net/socket.c    2005-08-18 10:30:35.000000000 +0200
@@ -375,7 +375,7 @@
 
        fd = get_unused_fd();
        if (fd >= 0) {
-               struct file *file = get_empty_filp();
+               struct file *file = get_empty_filp(FILP_NO_READ_AHEAD);
 
                if (!file) {
                        put_unused_fd(fd);
--- linux-2.6.13-rc6/fs/eventpoll.c     2005-08-07 20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/fs/eventpoll.c  2005-08-18 10:30:35.000000000 +0200
@@ -717,7 +717,7 @@
 
        /* Get an ready to use file */
        error = -ENFILE;
-       file = get_empty_filp();
+       file = get_empty_filp(FILP_NO_READ_AHEAD);
        if (!file)
                goto eexit_1;
 
--- linux-2.6.13-rc6/kernel/futex.c     2005-08-07 20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/kernel/futex.c  2005-08-18 10:30:35.000000000 +0200
@@ -661,7 +661,7 @@
        ret = get_unused_fd();
        if (ret < 0)
                goto out;
-       filp = get_empty_filp();
+       filp = get_empty_filp(FILP_NO_READ_AHEAD);
        if (!filp) {
                put_unused_fd(ret);
                ret = -ENFILE;
--- linux-2.6.13-rc6/mm/shmem.c 2005-08-07 20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/mm/shmem.c      2005-08-18 10:30:35.000000000 +0200
@@ -2272,7 +2272,7 @@
                goto put_memory;
 
        error = -ENFILE;
-       file = get_empty_filp();
+       file = get_empty_filp(FILP_WITH_READ_AHEAD);
        if (!file)
                goto put_dentry;
 
--- linux-2.6.13-rc6/fs/pipe.c  2005-08-07 20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/fs/pipe.c       2005-08-18 10:30:35.000000000 +0200
@@ -723,11 +723,11 @@
        int i,j;
 
        error = -ENFILE;
-       f1 = get_empty_filp();
+       f1 = get_empty_filp(FILP_NO_READ_AHEAD);
        if (!f1)
                goto no_files;
 
-       f2 = get_empty_filp();
+       f2 = get_empty_filp(FILP_NO_READ_AHEAD);
        if (!f2)
                goto close_f1;
 
--- linux-2.6.13-rc6/fs/inotify.c       2005-08-07 20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/fs/inotify.c    2005-08-18 10:30:35.000000000 +0200
@@ -865,7 +865,7 @@
        if (fd < 0)
                return fd;
 
-       filp = get_empty_filp();
+       filp = get_empty_filp(FILP_NO_READ_AHEAD);
        if (!filp) {
                ret = -ENFILE;
                goto out_put_fd;
--- linux-2.6.13-rc6/fs/hugetlbfs/inode.c       2005-08-07 20:18:56.000000000 
+0200
+++ linux-2.6.13-rc6-ed/fs/hugetlbfs/inode.c    2005-08-18 10:30:35.000000000 
+0200
@@ -785,7 +785,7 @@
                goto out_shm_unlock;
 
        error = -ENFILE;
-       file = get_empty_filp();
+       file = get_empty_filp(FILP_WITH_READ_AHEAD);
        if (!file)
                goto out_dentry;
 
--- linux-2.6.13-rc6/arch/ia64/kernel/perfmon.c 2005-08-07 20:18:56.000000000 
+0200
+++ linux-2.6.13-rc6-ed/arch/ia64/kernel/perfmon.c      2005-08-18 
10:36:28.000000000 +0200
@@ -2157,7 +2157,7 @@
 
        ret = -ENFILE;
 
-       file = get_empty_filp();
+       file = get_empty_filp(FILP_WITH_READ_AHEAD);
        if (!file) goto out;
 
        /*
--- linux-2.6.13-rc6/drivers/infiniband/core/uverbs_main.c      2005-08-07 
20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/drivers/infiniband/core/uverbs_main.c   2005-08-18 
10:30:35.000000000 +0200
@@ -367,7 +367,7 @@
        if (file->fd < 0)
                return file->fd;
 
-       filp = get_empty_filp();
+       filp = get_empty_filp(FILP_NO_READ_AHEAD);
        if (!filp) {
                put_unused_fd(file->fd);
                return -ENFILE;
--- linux-2.6.13-rc6/mm/tiny-shmem.c    2005-08-07 20:18:56.000000000 +0200
+++ linux-2.6.13-rc6-ed/mm/tiny-shmem.c 2005-08-18 10:30:35.000000000 +0200
@@ -68,7 +68,7 @@
                goto put_memory;
 
        error = -ENFILE;
-       file = get_empty_filp();
+       file = get_empty_filp(FILP_WITH_READ_AHEAD);
        if (!file)
                goto put_dentry;
 

Reply via email to