optimize compat_core_sys_select() by a using stack space for small fd sets
authorBadari Pulavarty <pbadari@us.ibm.com>
Wed, 23 May 2007 20:57:45 +0000 (13:57 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Thu, 24 May 2007 03:14:12 +0000 (20:14 -0700)
Optimize select by a using stack space for small fd sets.
core_sys_select() already has this optimization.  This is for compat
version.

Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/compat.c

index 1de2331..4db6216 100644 (file)
@@ -1544,9 +1544,10 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
        compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout)
 {
        fd_set_bits fds;
-       char *bits;
+       void *bits;
        int size, max_fds, ret = -EINVAL;
        struct fdtable *fdt;
+       long stack_fds[SELECT_STACK_ALLOC/sizeof(long)];
 
        if (n < 0)
                goto out_nofds;
@@ -1564,11 +1565,14 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
         * since we used fdset we need to allocate memory in units of
         * long-words.
         */
-       ret = -ENOMEM;
        size = FDS_BYTES(n);
-       bits = kmalloc(6 * size, GFP_KERNEL);
-       if (!bits)
-               goto out_nofds;
+       bits = stack_fds;
+       if (size > sizeof(stack_fds) / 6) {
+               bits = kmalloc(6 * size, GFP_KERNEL);
+               ret = -ENOMEM;
+               if (!bits)
+                       goto out_nofds;
+       }
        fds.in      = (unsigned long *)  bits;
        fds.out     = (unsigned long *) (bits +   size);
        fds.ex      = (unsigned long *) (bits + 2*size);
@@ -1600,7 +1604,8 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
            compat_set_fd_set(n, exp, fds.res_ex))
                ret = -EFAULT;
 out:
-       kfree(bits);
+       if (bits != stack_fds)
+               kfree(bits);
 out_nofds:
        return ret;
 }