Reduce the amount of code and shrink a .text section a bit:
[linux]$ ./scripts/bloat-o-meter -t /tmp/vmlinux.o.{old,new}
add/remove: 1/0 grow/shrink: 0/4 up/down: 284/-691 (-407)
Function                                     old     new   delta
do_sys_ppoll                                   -     284    +284
__x64_sys_ppoll                              214      42    -172
__ia32_sys_ppoll                             213      40    -173
__ia32_compat_sys_ppoll_time64               213      40    -173
__ia32_compat_sys_ppoll_time32               213      40    -173
Total: Before=13357557, After=13357150, chg -0.00%

The downside is that "tsp" and "sigmask" parameters gets (void *),
but it seems worth losing static type checking if there is only one
line in syscall definition.
Other way could be to add compat parameters in do_sys_ppoll(), but
that trashes 2 more registers..

Signed-off-by: Dmitry Safonov <d...@arista.com>
---
 fs/select.c | 94 ++++++++++++++++++-----------------------------------
 1 file changed, 32 insertions(+), 62 deletions(-)

diff --git a/fs/select.c b/fs/select.c
index 458f2a944318..262300e58370 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -1056,54 +1056,58 @@ SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, 
unsigned int, nfds,
        return ret;
 }
 
-SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
-               struct __kernel_timespec __user *, tsp, const sigset_t __user 
*, sigmask,
-               size_t, sigsetsize)
+static int do_sys_ppoll(struct pollfd __user *ufds, unsigned int nfds,
+                       void __user *tsp, const void __user *sigmask,
+                       size_t sigsetsize, enum poll_time_type pt_type)
 {
        struct timespec64 ts, end_time, *to = NULL;
        int ret;
 
        if (tsp) {
-               if (get_timespec64(&ts, tsp))
-                       return -EFAULT;
+               switch (pt_type) {
+               case PT_TIMESPEC:
+                       if (get_timespec64(&ts, tsp))
+                               return -EFAULT;
+                       break;
+               case PT_OLD_TIMESPEC:
+                       if (get_old_timespec32(&ts, tsp))
+                               return -EFAULT;
+                       break;
+               default:
+                       WARN_ON_ONCE(1);
+                       return -ENOSYS;
+               }
 
                to = &end_time;
                if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
                        return -EINVAL;
        }
 
-       ret = set_user_sigmask(sigmask, sigsetsize);
+       if (!in_compat_syscall())
+               ret = set_user_sigmask(sigmask, sigsetsize);
+       else
+               ret = set_compat_user_sigmask(sigmask, sigsetsize);
+
        if (ret)
                return ret;
 
        ret = do_sys_poll(ufds, nfds, to);
-       return poll_select_finish(&end_time, tsp, PT_TIMESPEC, ret);
+       return poll_select_finish(&end_time, tsp, pt_type, ret);
 }
 
-#if defined(CONFIG_COMPAT_32BIT_TIME) && !defined(CONFIG_64BIT)
+SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
+               struct __kernel_timespec __user *, tsp, const sigset_t __user 
*, sigmask,
+               size_t, sigsetsize)
+{
+       return do_sys_ppoll(ufds, nfds, tsp, sigmask, sigsetsize, PT_TIMESPEC);
+}
 
+#if defined(CONFIG_COMPAT_32BIT_TIME) && !defined(CONFIG_64BIT)
 SYSCALL_DEFINE5(ppoll_time32, struct pollfd __user *, ufds, unsigned int, nfds,
                struct old_timespec32 __user *, tsp, const sigset_t __user *, 
sigmask,
                size_t, sigsetsize)
 {
-       struct timespec64 ts, end_time, *to = NULL;
-       int ret;
-
-       if (tsp) {
-               if (get_old_timespec32(&ts, tsp))
-                       return -EFAULT;
-
-               to = &end_time;
-               if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
-                       return -EINVAL;
-       }
-
-       ret = set_user_sigmask(sigmask, sigsetsize);
-       if (ret)
-               return ret;
-
-       ret = do_sys_poll(ufds, nfds, to);
-       return poll_select_finish(&end_time, tsp, PT_OLD_TIMESPEC, ret);
+       return do_sys_ppoll(ufds, nfds, tsp, sigmask, sigsetsize, 
PT_OLD_TIMESPEC);
 }
 #endif
 
@@ -1352,24 +1356,7 @@ COMPAT_SYSCALL_DEFINE5(ppoll_time32, struct pollfd 
__user *, ufds,
        unsigned int,  nfds, struct old_timespec32 __user *, tsp,
        const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize)
 {
-       struct timespec64 ts, end_time, *to = NULL;
-       int ret;
-
-       if (tsp) {
-               if (get_old_timespec32(&ts, tsp))
-                       return -EFAULT;
-
-               to = &end_time;
-               if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
-                       return -EINVAL;
-       }
-
-       ret = set_compat_user_sigmask(sigmask, sigsetsize);
-       if (ret)
-               return ret;
-
-       ret = do_sys_poll(ufds, nfds, to);
-       return poll_select_finish(&end_time, tsp, PT_OLD_TIMESPEC, ret);
+       return do_sys_ppoll(ufds, nfds, tsp, sigmask, sigsetsize, 
PT_OLD_TIMESPEC);
 }
 #endif
 
@@ -1378,24 +1365,7 @@ COMPAT_SYSCALL_DEFINE5(ppoll_time64, struct pollfd 
__user *, ufds,
        unsigned int,  nfds, struct __kernel_timespec __user *, tsp,
        const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize)
 {
-       struct timespec64 ts, end_time, *to = NULL;
-       int ret;
-
-       if (tsp) {
-               if (get_timespec64(&ts, tsp))
-                       return -EFAULT;
-
-               to = &end_time;
-               if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
-                       return -EINVAL;
-       }
-
-       ret = set_compat_user_sigmask(sigmask, sigsetsize);
-       if (ret)
-               return ret;
-
-       ret = do_sys_poll(ufds, nfds, to);
-       return poll_select_finish(&end_time, tsp, PT_TIMESPEC, ret);
+       return do_sys_ppoll(ufds, nfds, tsp, sigmask, sigsetsize, PT_TIMESPEC);
 }
 
 #endif
-- 
2.23.0

Reply via email to