aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2008-08-31 11:26:40 -0400
committerArjan van de Ven <arjan@linux.intel.com>2008-09-06 00:35:03 -0400
commit8ff3e8e85fa6c312051134b3953e397feb639f51 (patch)
tree526886377ca92a62f030c25bc8f91f13a6f991eb /fs/compat.c
parentbe5dad20a55e054a35dac7f6f5f184dc72b379b4 (diff)
select: switch select() and poll() over to hrtimers
With lots of help, input and cleanups from Thomas Gleixner This patch switches select() and poll() over to hrtimers. The core of the patch is replacing the "s64 timeout" with a "struct timespec end_time" in all the plumbing. But most of the diffstat comes from using the just introduced helpers: poll_select_set_timeout poll_select_copy_remaining timespec_add_safe which make manipulating the timespec easier and less error-prone. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c136
1 files changed, 20 insertions, 116 deletions
diff --git a/fs/compat.c b/fs/compat.c
index 424767c954a0..133ed7f5d681 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1568,7 +1568,8 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1568 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) 1568 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
1569 1569
1570int compat_core_sys_select(int n, compat_ulong_t __user *inp, 1570int compat_core_sys_select(int n, compat_ulong_t __user *inp,
1571 compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout) 1571 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1572 struct timespec *end_time)
1572{ 1573{
1573 fd_set_bits fds; 1574 fd_set_bits fds;
1574 void *bits; 1575 void *bits;
@@ -1615,7 +1616,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
1615 zero_fd_set(n, fds.res_out); 1616 zero_fd_set(n, fds.res_out);
1616 zero_fd_set(n, fds.res_ex); 1617 zero_fd_set(n, fds.res_ex);
1617 1618
1618 ret = do_select(n, &fds, timeout); 1619 ret = do_select(n, &fds, end_time);
1619 1620
1620 if (ret < 0) 1621 if (ret < 0)
1621 goto out; 1622 goto out;
@@ -1641,7 +1642,7 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
1641 compat_ulong_t __user *outp, compat_ulong_t __user *exp, 1642 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1642 struct compat_timeval __user *tvp) 1643 struct compat_timeval __user *tvp)
1643{ 1644{
1644 s64 timeout = -1; 1645 struct timespec end_time, *to = NULL;
1645 struct compat_timeval tv; 1646 struct compat_timeval tv;
1646 int ret; 1647 int ret;
1647 1648
@@ -1649,43 +1650,14 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
1649 if (copy_from_user(&tv, tvp, sizeof(tv))) 1650 if (copy_from_user(&tv, tvp, sizeof(tv)))
1650 return -EFAULT; 1651 return -EFAULT;
1651 1652
1652 if (tv.tv_sec < 0 || tv.tv_usec < 0) 1653 to = &end_time;
1654 if (poll_select_set_timeout(to, tv.tv_sec,
1655 tv.tv_usec * NSEC_PER_USEC))
1653 return -EINVAL; 1656 return -EINVAL;
1654
1655 /* Cast to u64 to make GCC stop complaining */
1656 if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
1657 timeout = -1; /* infinite */
1658 else {
1659 timeout = DIV_ROUND_UP(tv.tv_usec, 1000000/HZ);
1660 timeout += tv.tv_sec * HZ;
1661 }
1662 } 1657 }
1663 1658
1664 ret = compat_core_sys_select(n, inp, outp, exp, &timeout); 1659 ret = compat_core_sys_select(n, inp, outp, exp, to);
1665 1660 ret = poll_select_copy_remaining(&end_time, tvp, 1, ret);
1666 if (tvp) {
1667 struct compat_timeval rtv;
1668
1669 if (current->personality & STICKY_TIMEOUTS)
1670 goto sticky;
1671 rtv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
1672 rtv.tv_sec = timeout;
1673 if (compat_timeval_compare(&rtv, &tv) >= 0)
1674 rtv = tv;
1675 if (copy_to_user(tvp, &rtv, sizeof(rtv))) {
1676sticky:
1677 /*
1678 * If an application puts its timeval in read-only
1679 * memory, we don't want the Linux-specific update to
1680 * the timeval to cause a fault after the select has
1681 * completed successfully. However, because we're not
1682 * updating the timeval, we can't restart the system
1683 * call.
1684 */
1685 if (ret == -ERESTARTNOHAND)
1686 ret = -EINTR;
1687 }
1688 }
1689 1661
1690 return ret; 1662 return ret;
1691} 1663}
@@ -1698,15 +1670,16 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
1698{ 1670{
1699 compat_sigset_t ss32; 1671 compat_sigset_t ss32;
1700 sigset_t ksigmask, sigsaved; 1672 sigset_t ksigmask, sigsaved;
1701 s64 timeout = MAX_SCHEDULE_TIMEOUT;
1702 struct compat_timespec ts; 1673 struct compat_timespec ts;
1674 struct timespec end_time, *to = NULL;
1703 int ret; 1675 int ret;
1704 1676
1705 if (tsp) { 1677 if (tsp) {
1706 if (copy_from_user(&ts, tsp, sizeof(ts))) 1678 if (copy_from_user(&ts, tsp, sizeof(ts)))
1707 return -EFAULT; 1679 return -EFAULT;
1708 1680
1709 if (ts.tv_sec < 0 || ts.tv_nsec < 0) 1681 to = &end_time;
1682 if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1710 return -EINVAL; 1683 return -EINVAL;
1711 } 1684 }
1712 1685
@@ -1721,51 +1694,8 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
1721 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); 1694 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1722 } 1695 }
1723 1696
1724 do { 1697 ret = compat_core_sys_select(n, inp, outp, exp, to);
1725 if (tsp) { 1698 ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
1726 if ((unsigned long)ts.tv_sec < MAX_SELECT_SECONDS) {
1727 timeout = DIV_ROUND_UP(ts.tv_nsec, 1000000000/HZ);
1728 timeout += ts.tv_sec * (unsigned long)HZ;
1729 ts.tv_sec = 0;
1730 ts.tv_nsec = 0;
1731 } else {
1732 ts.tv_sec -= MAX_SELECT_SECONDS;
1733 timeout = MAX_SELECT_SECONDS * HZ;
1734 }
1735 }
1736
1737 ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
1738
1739 } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec));
1740
1741 if (tsp) {
1742 struct compat_timespec rts;
1743
1744 if (current->personality & STICKY_TIMEOUTS)
1745 goto sticky;
1746
1747 rts.tv_sec = timeout / HZ;
1748 rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ);
1749 if (rts.tv_nsec >= NSEC_PER_SEC) {
1750 rts.tv_sec++;
1751 rts.tv_nsec -= NSEC_PER_SEC;
1752 }
1753 if (compat_timespec_compare(&rts, &ts) >= 0)
1754 rts = ts;
1755 if (copy_to_user(tsp, &rts, sizeof(rts))) {
1756sticky:
1757 /*
1758 * If an application puts its timeval in read-only
1759 * memory, we don't want the Linux-specific update to
1760 * the timeval to cause a fault after the select has
1761 * completed successfully. However, because we're not
1762 * updating the timeval, we can't restart the system
1763 * call.
1764 */
1765 if (ret == -ERESTARTNOHAND)
1766 ret = -EINTR;
1767 }
1768 }
1769 1699
1770 if (ret == -ERESTARTNOHAND) { 1700 if (ret == -ERESTARTNOHAND) {
1771 /* 1701 /*
@@ -1810,18 +1740,16 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
1810 compat_sigset_t ss32; 1740 compat_sigset_t ss32;
1811 sigset_t ksigmask, sigsaved; 1741 sigset_t ksigmask, sigsaved;
1812 struct compat_timespec ts; 1742 struct compat_timespec ts;
1813 s64 timeout = -1; 1743 struct timespec end_time, *to = NULL;
1814 int ret; 1744 int ret;
1815 1745
1816 if (tsp) { 1746 if (tsp) {
1817 if (copy_from_user(&ts, tsp, sizeof(ts))) 1747 if (copy_from_user(&ts, tsp, sizeof(ts)))
1818 return -EFAULT; 1748 return -EFAULT;
1819 1749
1820 /* We assume that ts.tv_sec is always lower than 1750 to = &end_time;
1821 the number of seconds that can be expressed in 1751 if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1822 an s64. Otherwise the compiler bitches at us */ 1752 return -EINVAL;
1823 timeout = DIV_ROUND_UP(ts.tv_nsec, 1000000000/HZ);
1824 timeout += ts.tv_sec * HZ;
1825 } 1753 }
1826 1754
1827 if (sigmask) { 1755 if (sigmask) {
@@ -1835,7 +1763,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
1835 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); 1763 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1836 } 1764 }
1837 1765
1838 ret = do_sys_poll(ufds, nfds, &timeout); 1766 ret = do_sys_poll(ufds, nfds, to);
1839 1767
1840 /* We can restart this syscall, usually */ 1768 /* We can restart this syscall, usually */
1841 if (ret == -EINTR) { 1769 if (ret == -EINTR) {
@@ -1853,31 +1781,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
1853 } else if (sigmask) 1781 } else if (sigmask)
1854 sigprocmask(SIG_SETMASK, &sigsaved, NULL); 1782 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1855 1783
1856 if (tsp && timeout >= 0) { 1784 ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
1857 struct compat_timespec rts;
1858
1859 if (current->personality & STICKY_TIMEOUTS)
1860 goto sticky;
1861 /* Yes, we know it's actually an s64, but it's also positive. */
1862 rts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) *
1863 1000;
1864 rts.tv_sec = timeout;
1865 if (compat_timespec_compare(&rts, &ts) >= 0)
1866 rts = ts;
1867 if (copy_to_user(tsp, &rts, sizeof(rts))) {
1868sticky:
1869 /*
1870 * If an application puts its timeval in read-only
1871 * memory, we don't want the Linux-specific update to
1872 * the timeval to cause a fault after the select has
1873 * completed successfully. However, because we're not
1874 * updating the timeval, we can't restart the system
1875 * call.
1876 */
1877 if (ret == -ERESTARTNOHAND && timeout >= 0)
1878 ret = -EINTR;
1879 }
1880 }
1881 1785
1882 return ret; 1786 return ret;
1883} 1787}