aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-10-23 13:53:02 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-23 13:53:02 -0400
commit1f6d6e8ebe73ba9d9d4c693f7f6f50f661dbd6e4 (patch)
treebe7a2d20b1728da5a0d844a6f4cd382b2c2569fb /fs/compat.c
parentdb563fc2e80534f98c7f9121a6f7dfe41f177a79 (diff)
parent268a3dcfea2077fca60d3715caa5c96f9b5e6ea7 (diff)
Merge branch 'v28-range-hrtimers-for-linus-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'v28-range-hrtimers-for-linus-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (37 commits) hrtimers: add missing docbook comments to struct hrtimer hrtimers: simplify hrtimer_peek_ahead_timers() hrtimers: fix docbook comments DECLARE_PER_CPU needs linux/percpu.h hrtimers: fix typo rangetimers: fix the bug reported by Ingo for real rangetimer: fix BUG_ON reported by Ingo rangetimer: fix x86 build failure for the !HRTIMERS case select: fix alpha OSF wrapper select: fix alpha OSF wrapper hrtimer: peek at the timer queue just before going idle hrtimer: make the futex() system call use the per process slack value hrtimer: make the nanosleep() syscall use the per process slack hrtimer: fix signed/unsigned bug in slack estimator hrtimer: show the timer ranges in /proc/timer_list hrtimer: incorporate feedback from Peter Zijlstra hrtimer: add a hrtimer_start_range() function hrtimer: another build fix hrtimer: fix build bug found by Ingo hrtimer: make select() and poll() use the hrtimer range feature ...
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c187
1 files changed, 71 insertions, 116 deletions
diff --git a/fs/compat.c b/fs/compat.c
index cb36245f9fe0..fe3c9bf87608 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1469,6 +1469,57 @@ out_ret:
1469 1469
1470#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) 1470#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t))
1471 1471
1472static int poll_select_copy_remaining(struct timespec *end_time, void __user *p,
1473 int timeval, int ret)
1474{
1475 struct timespec ts;
1476
1477 if (!p)
1478 return ret;
1479
1480 if (current->personality & STICKY_TIMEOUTS)
1481 goto sticky;
1482
1483 /* No update for zero timeout */
1484 if (!end_time->tv_sec && !end_time->tv_nsec)
1485 return ret;
1486
1487 ktime_get_ts(&ts);
1488 ts = timespec_sub(*end_time, ts);
1489 if (ts.tv_sec < 0)
1490 ts.tv_sec = ts.tv_nsec = 0;
1491
1492 if (timeval) {
1493 struct compat_timeval rtv;
1494
1495 rtv.tv_sec = ts.tv_sec;
1496 rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
1497
1498 if (!copy_to_user(p, &rtv, sizeof(rtv)))
1499 return ret;
1500 } else {
1501 struct compat_timespec rts;
1502
1503 rts.tv_sec = ts.tv_sec;
1504 rts.tv_nsec = ts.tv_nsec;
1505
1506 if (!copy_to_user(p, &rts, sizeof(rts)))
1507 return ret;
1508 }
1509 /*
1510 * If an application puts its timeval in read-only memory, we
1511 * don't want the Linux-specific update to the timeval to
1512 * cause a fault after the select has completed
1513 * successfully. However, because we're not updating the
1514 * timeval, we can't restart the system call.
1515 */
1516
1517sticky:
1518 if (ret == -ERESTARTNOHAND)
1519 ret = -EINTR;
1520 return ret;
1521}
1522
1472/* 1523/*
1473 * Ooo, nasty. We need here to frob 32-bit unsigned longs to 1524 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
1474 * 64-bit unsigned longs. 1525 * 64-bit unsigned longs.
@@ -1550,7 +1601,8 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
1550 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1) 1601 ((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
1551 1602
1552int compat_core_sys_select(int n, compat_ulong_t __user *inp, 1603int compat_core_sys_select(int n, compat_ulong_t __user *inp,
1553 compat_ulong_t __user *outp, compat_ulong_t __user *exp, s64 *timeout) 1604 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1605 struct timespec *end_time)
1554{ 1606{
1555 fd_set_bits fds; 1607 fd_set_bits fds;
1556 void *bits; 1608 void *bits;
@@ -1597,7 +1649,7 @@ int compat_core_sys_select(int n, compat_ulong_t __user *inp,
1597 zero_fd_set(n, fds.res_out); 1649 zero_fd_set(n, fds.res_out);
1598 zero_fd_set(n, fds.res_ex); 1650 zero_fd_set(n, fds.res_ex);
1599 1651
1600 ret = do_select(n, &fds, timeout); 1652 ret = do_select(n, &fds, end_time);
1601 1653
1602 if (ret < 0) 1654 if (ret < 0)
1603 goto out; 1655 goto out;
@@ -1623,7 +1675,7 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
1623 compat_ulong_t __user *outp, compat_ulong_t __user *exp, 1675 compat_ulong_t __user *outp, compat_ulong_t __user *exp,
1624 struct compat_timeval __user *tvp) 1676 struct compat_timeval __user *tvp)
1625{ 1677{
1626 s64 timeout = -1; 1678 struct timespec end_time, *to = NULL;
1627 struct compat_timeval tv; 1679 struct compat_timeval tv;
1628 int ret; 1680 int ret;
1629 1681
@@ -1631,43 +1683,14 @@ asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp,
1631 if (copy_from_user(&tv, tvp, sizeof(tv))) 1683 if (copy_from_user(&tv, tvp, sizeof(tv)))
1632 return -EFAULT; 1684 return -EFAULT;
1633 1685
1634 if (tv.tv_sec < 0 || tv.tv_usec < 0) 1686 to = &end_time;
1687 if (poll_select_set_timeout(to, tv.tv_sec,
1688 tv.tv_usec * NSEC_PER_USEC))
1635 return -EINVAL; 1689 return -EINVAL;
1636
1637 /* Cast to u64 to make GCC stop complaining */
1638 if ((u64)tv.tv_sec >= (u64)MAX_INT64_SECONDS)
1639 timeout = -1; /* infinite */
1640 else {
1641 timeout = DIV_ROUND_UP(tv.tv_usec, 1000000/HZ);
1642 timeout += tv.tv_sec * HZ;
1643 }
1644 } 1690 }
1645 1691
1646 ret = compat_core_sys_select(n, inp, outp, exp, &timeout); 1692 ret = compat_core_sys_select(n, inp, outp, exp, to);
1647 1693 ret = poll_select_copy_remaining(&end_time, tvp, 1, ret);
1648 if (tvp) {
1649 struct compat_timeval rtv;
1650
1651 if (current->personality & STICKY_TIMEOUTS)
1652 goto sticky;
1653 rtv.tv_usec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ));
1654 rtv.tv_sec = timeout;
1655 if (compat_timeval_compare(&rtv, &tv) >= 0)
1656 rtv = tv;
1657 if (copy_to_user(tvp, &rtv, sizeof(rtv))) {
1658sticky:
1659 /*
1660 * If an application puts its timeval in read-only
1661 * memory, we don't want the Linux-specific update to
1662 * the timeval to cause a fault after the select has
1663 * completed successfully. However, because we're not
1664 * updating the timeval, we can't restart the system
1665 * call.
1666 */
1667 if (ret == -ERESTARTNOHAND)
1668 ret = -EINTR;
1669 }
1670 }
1671 1694
1672 return ret; 1695 return ret;
1673} 1696}
@@ -1680,15 +1703,16 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
1680{ 1703{
1681 compat_sigset_t ss32; 1704 compat_sigset_t ss32;
1682 sigset_t ksigmask, sigsaved; 1705 sigset_t ksigmask, sigsaved;
1683 s64 timeout = MAX_SCHEDULE_TIMEOUT;
1684 struct compat_timespec ts; 1706 struct compat_timespec ts;
1707 struct timespec end_time, *to = NULL;
1685 int ret; 1708 int ret;
1686 1709
1687 if (tsp) { 1710 if (tsp) {
1688 if (copy_from_user(&ts, tsp, sizeof(ts))) 1711 if (copy_from_user(&ts, tsp, sizeof(ts)))
1689 return -EFAULT; 1712 return -EFAULT;
1690 1713
1691 if (ts.tv_sec < 0 || ts.tv_nsec < 0) 1714 to = &end_time;
1715 if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1692 return -EINVAL; 1716 return -EINVAL;
1693 } 1717 }
1694 1718
@@ -1703,51 +1727,8 @@ asmlinkage long compat_sys_pselect7(int n, compat_ulong_t __user *inp,
1703 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); 1727 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1704 } 1728 }
1705 1729
1706 do { 1730 ret = compat_core_sys_select(n, inp, outp, exp, to);
1707 if (tsp) { 1731 ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
1708 if ((unsigned long)ts.tv_sec < MAX_SELECT_SECONDS) {
1709 timeout = DIV_ROUND_UP(ts.tv_nsec, 1000000000/HZ);
1710 timeout += ts.tv_sec * (unsigned long)HZ;
1711 ts.tv_sec = 0;
1712 ts.tv_nsec = 0;
1713 } else {
1714 ts.tv_sec -= MAX_SELECT_SECONDS;
1715 timeout = MAX_SELECT_SECONDS * HZ;
1716 }
1717 }
1718
1719 ret = compat_core_sys_select(n, inp, outp, exp, &timeout);
1720
1721 } while (!ret && !timeout && tsp && (ts.tv_sec || ts.tv_nsec));
1722
1723 if (tsp) {
1724 struct compat_timespec rts;
1725
1726 if (current->personality & STICKY_TIMEOUTS)
1727 goto sticky;
1728
1729 rts.tv_sec = timeout / HZ;
1730 rts.tv_nsec = (timeout % HZ) * (NSEC_PER_SEC/HZ);
1731 if (rts.tv_nsec >= NSEC_PER_SEC) {
1732 rts.tv_sec++;
1733 rts.tv_nsec -= NSEC_PER_SEC;
1734 }
1735 if (compat_timespec_compare(&rts, &ts) >= 0)
1736 rts = ts;
1737 if (copy_to_user(tsp, &rts, sizeof(rts))) {
1738sticky:
1739 /*
1740 * If an application puts its timeval in read-only
1741 * memory, we don't want the Linux-specific update to
1742 * the timeval to cause a fault after the select has
1743 * completed successfully. However, because we're not
1744 * updating the timeval, we can't restart the system
1745 * call.
1746 */
1747 if (ret == -ERESTARTNOHAND)
1748 ret = -EINTR;
1749 }
1750 }
1751 1732
1752 if (ret == -ERESTARTNOHAND) { 1733 if (ret == -ERESTARTNOHAND) {
1753 /* 1734 /*
@@ -1792,18 +1773,16 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
1792 compat_sigset_t ss32; 1773 compat_sigset_t ss32;
1793 sigset_t ksigmask, sigsaved; 1774 sigset_t ksigmask, sigsaved;
1794 struct compat_timespec ts; 1775 struct compat_timespec ts;
1795 s64 timeout = -1; 1776 struct timespec end_time, *to = NULL;
1796 int ret; 1777 int ret;
1797 1778
1798 if (tsp) { 1779 if (tsp) {
1799 if (copy_from_user(&ts, tsp, sizeof(ts))) 1780 if (copy_from_user(&ts, tsp, sizeof(ts)))
1800 return -EFAULT; 1781 return -EFAULT;
1801 1782
1802 /* We assume that ts.tv_sec is always lower than 1783 to = &end_time;
1803 the number of seconds that can be expressed in 1784 if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
1804 an s64. Otherwise the compiler bitches at us */ 1785 return -EINVAL;
1805 timeout = DIV_ROUND_UP(ts.tv_nsec, 1000000000/HZ);
1806 timeout += ts.tv_sec * HZ;
1807 } 1786 }
1808 1787
1809 if (sigmask) { 1788 if (sigmask) {
@@ -1817,7 +1796,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
1817 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); 1796 sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
1818 } 1797 }
1819 1798
1820 ret = do_sys_poll(ufds, nfds, &timeout); 1799 ret = do_sys_poll(ufds, nfds, to);
1821 1800
1822 /* We can restart this syscall, usually */ 1801 /* We can restart this syscall, usually */
1823 if (ret == -EINTR) { 1802 if (ret == -EINTR) {
@@ -1835,31 +1814,7 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
1835 } else if (sigmask) 1814 } else if (sigmask)
1836 sigprocmask(SIG_SETMASK, &sigsaved, NULL); 1815 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
1837 1816
1838 if (tsp && timeout >= 0) { 1817 ret = poll_select_copy_remaining(&end_time, tsp, 0, ret);
1839 struct compat_timespec rts;
1840
1841 if (current->personality & STICKY_TIMEOUTS)
1842 goto sticky;
1843 /* Yes, we know it's actually an s64, but it's also positive. */
1844 rts.tv_nsec = jiffies_to_usecs(do_div((*(u64*)&timeout), HZ)) *
1845 1000;
1846 rts.tv_sec = timeout;
1847 if (compat_timespec_compare(&rts, &ts) >= 0)
1848 rts = ts;
1849 if (copy_to_user(tsp, &rts, sizeof(rts))) {
1850sticky:
1851 /*
1852 * If an application puts its timeval in read-only
1853 * memory, we don't want the Linux-specific update to
1854 * the timeval to cause a fault after the select has
1855 * completed successfully. However, because we're not
1856 * updating the timeval, we can't restart the system
1857 * call.
1858 */
1859 if (ret == -ERESTARTNOHAND && timeout >= 0)
1860 ret = -EINTR;
1861 }
1862 }
1863 1818
1864 return ret; 1819 return ret;
1865} 1820}