diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-23 13:53:02 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-23 13:53:02 -0400 |
commit | 1f6d6e8ebe73ba9d9d4c693f7f6f50f661dbd6e4 (patch) | |
tree | be7a2d20b1728da5a0d844a6f4cd382b2c2569fb /fs/compat.c | |
parent | db563fc2e80534f98c7f9121a6f7dfe41f177a79 (diff) | |
parent | 268a3dcfea2077fca60d3715caa5c96f9b5e6ea7 (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.c | 187 |
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 | ||
1472 | static 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 | |||
1517 | sticky: | ||
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 | ||
1552 | int compat_core_sys_select(int n, compat_ulong_t __user *inp, | 1603 | int 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))) { | ||
1658 | sticky: | ||
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))) { | ||
1738 | sticky: | ||
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))) { | ||
1850 | sticky: | ||
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 | } |