aboutsummaryrefslogtreecommitdiffstats
path: root/fs/compat.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2008-08-31 11:16:57 -0400
committerArjan van de Ven <arjan@linux.intel.com>2008-09-06 00:34:59 -0400
commitb773ad40aca5bd755ba886620842f16e8fef6d75 (patch)
tree7065661f6559aff70244f2805ced48f894c9b38c /fs/compat.c
parentdf0cc0539b4127bd02f64de2c335b4af1fdb3845 (diff)
select: add poll_select_set_timeout() and poll_select_copy_remaining() helpers
This patch adds 2 helpers that will be used for the hrtimer based select/poll: poll_select_set_timeout() is a helper that takes a timeout (as a second, nanosecond pair) and turns that into a "struct timespec" that represents the absolute end time. This is a common operation in the many select() and poll() variants and needs various, common, sanity checks. poll_select_copy_remaining() is a helper that takes care of copying the remaining time to userspace, as select(), pselect() and ppoll() do. This function comes in both a natural and a compat implementation (due to datastructure differences). Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Diffstat (limited to 'fs/compat.c')
-rw-r--r--fs/compat.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/fs/compat.c b/fs/compat.c
index 075d0509970d..424767c954a0 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1436,6 +1436,57 @@ out_ret:
1436 1436
1437#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) 1437#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t))
1438 1438
1439static int poll_select_copy_remaining(struct timespec *end_time, void __user *p,
1440 int timeval, int ret)
1441{
1442 struct timespec ts;
1443
1444 if (!p)
1445 return ret;
1446
1447 if (current->personality & STICKY_TIMEOUTS)
1448 goto sticky;
1449
1450 /* No update for zero timeout */
1451 if (!end_time->tv_sec && !end_time->tv_nsec)
1452 return ret;
1453
1454 ktime_get_ts(&ts);
1455 ts = timespec_sub(*end_time, ts);
1456 if (ts.tv_sec < 0)
1457 ts.tv_sec = ts.tv_nsec = 0;
1458
1459 if (timeval) {
1460 struct compat_timeval rtv;
1461
1462 rtv.tv_sec = ts.tv_sec;
1463 rtv.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
1464
1465 if (!copy_to_user(p, &rtv, sizeof(rtv)))
1466 return ret;
1467 } else {
1468 struct compat_timespec rts;
1469
1470 rts.tv_sec = ts.tv_sec;
1471 rts.tv_nsec = ts.tv_nsec;
1472
1473 if (!copy_to_user(p, &rts, sizeof(rts)))
1474 return ret;
1475 }
1476 /*
1477 * If an application puts its timeval in read-only memory, we
1478 * don't want the Linux-specific update to the timeval to
1479 * cause a fault after the select has completed
1480 * successfully. However, because we're not updating the
1481 * timeval, we can't restart the system call.
1482 */
1483
1484sticky:
1485 if (ret == -ERESTARTNOHAND)
1486 ret = -EINTR;
1487 return ret;
1488}
1489
1439/* 1490/*
1440 * Ooo, nasty. We need here to frob 32-bit unsigned longs to 1491 * Ooo, nasty. We need here to frob 32-bit unsigned longs to
1441 * 64-bit unsigned longs. 1492 * 64-bit unsigned longs.