[PATCH] Hook compat_sys_nanosleep up to high res timer code

From: Anton Blanchard
Date: Sun Oct 14 2007 - 17:58:41 EST



Now we have high res timers on ppc64 I thought Id test them. It turns
out compat_sys_nanosleep hasnt been converted to the hrtimer code and so
is limited to HZ resolution.

The following patch makes compat_sys_nanosleep call hrtimer_nanosleep
and uses compat_alloc_user_space to avoid setting KERNEL_DS.

Signed-off-by: Anton Blanchard <anton@xxxxxxxxx>
---

diff --git a/kernel/compat.c b/kernel/compat.c
index 3bae374..46795ac 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -40,62 +40,29 @@ int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user
__put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
}

-static long compat_nanosleep_restart(struct restart_block *restart)
-{
- unsigned long expire = restart->arg0, now = jiffies;
- struct compat_timespec __user *rmtp;
-
- /* Did it expire while we handled signals? */
- if (!time_after(expire, now))
- return 0;
-
- expire = schedule_timeout_interruptible(expire - now);
- if (expire == 0)
- return 0;
-
- rmtp = (struct compat_timespec __user *)restart->arg1;
- if (rmtp) {
- struct compat_timespec ct;
- struct timespec t;
-
- jiffies_to_timespec(expire, &t);
- ct.tv_sec = t.tv_sec;
- ct.tv_nsec = t.tv_nsec;
- if (copy_to_user(rmtp, &ct, sizeof(ct)))
- return -EFAULT;
- }
- /* The 'restart' block is already filled in */
- return -ERESTART_RESTARTBLOCK;
-}
-
asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
- struct compat_timespec __user *rmtp)
+ struct compat_timespec __user *rmtp)
{
- struct timespec t;
- struct restart_block *restart;
- unsigned long expire;
+ struct timespec tu;
+ struct timespec __user *rmtp64;
+ long ret;

- if (get_compat_timespec(&t, rqtp))
+ if (get_compat_timespec(&tu, rqtp))
return -EFAULT;

- if ((t.tv_nsec >= 1000000000L) || (t.tv_nsec < 0) || (t.tv_sec < 0))
+ if (!timespec_valid(&tu))
return -EINVAL;

- expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
- expire = schedule_timeout_interruptible(expire);
- if (expire == 0)
- return 0;
+ rmtp64 = compat_alloc_user_space(sizeof(*rmtp64));
+ ret = hrtimer_nanosleep(&tu, rmtp64, HRTIMER_MODE_REL, CLOCK_MONOTONIC);

- if (rmtp) {
- jiffies_to_timespec(expire, &t);
- if (put_compat_timespec(&t, rmtp))
+ if (ret) {
+ if (copy_from_user(&tu, rmtp64, sizeof(*rmtp64)) ||
+ put_compat_timespec(&tu, rmtp))
return -EFAULT;
}
- restart = &current_thread_info()->restart_block;
- restart->fn = compat_nanosleep_restart;
- restart->arg0 = jiffies + expire;
- restart->arg1 = (unsigned long) rmtp;
- return -ERESTART_RESTARTBLOCK;
+
+ return ret;
}

static inline long get_compat_itimerval(struct itimerval *o,
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/