- struct timespec nowts;
- long timeout;
-
- if (p) {
- if (unlikely(p->tv_nsec < 0 || p->tv_sec < 0
- || p->tv_nsec >= NSEC_PER_SEC))
- return -EINVAL;
- nowts = CURRENT_TIME;
- /* first subtract as jiffies can't be too big */
- p->tv_sec -= nowts.tv_sec;
- if (p->tv_nsec < nowts.tv_nsec) {
- p->tv_nsec += NSEC_PER_SEC;
- p->tv_sec--;
- }
- p->tv_nsec -= nowts.tv_nsec;
- if (p->tv_sec < 0)
- return 0;
-
- timeout = timespec_to_jiffies(p) + 1;
- } else
- return MAX_SCHEDULE_TIMEOUT;
+ if (copy_from_user(ts, u_abs_timeout, sizeof(struct timespec)))
+ return -EFAULT;
+ if (!timespec_valid(ts))
+ return -EINVAL;