Commit 58f9b52ee8712283f7ffedb661df678c61e88a91

Authored by Linus Torvalds

Merge ssh://master.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-hrt

* ssh://master.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-hrt:
  hrtimer: hook compat_sys_nanosleep up to high res timer code
  hrtimer: Rework hrtimer_nanosleep to make sys_compat_nanosleep easier

Showing 4 changed files Side-by-side Diff

include/linux/hrtimer.h
... ... @@ -300,7 +300,7 @@
300 300  
301 301 /* Precise sleep: */
302 302 extern long hrtimer_nanosleep(struct timespec *rqtp,
303   - struct timespec __user *rmtp,
  303 + struct timespec *rmtp,
304 304 const enum hrtimer_mode mode,
305 305 const clockid_t clockid);
306 306 extern long hrtimer_nanosleep_restart(struct restart_block *restart_block);
... ... @@ -40,62 +40,27 @@
40 40 __put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
41 41 }
42 42  
43   -static long compat_nanosleep_restart(struct restart_block *restart)
44   -{
45   - unsigned long expire = restart->arg0, now = jiffies;
46   - struct compat_timespec __user *rmtp;
47   -
48   - /* Did it expire while we handled signals? */
49   - if (!time_after(expire, now))
50   - return 0;
51   -
52   - expire = schedule_timeout_interruptible(expire - now);
53   - if (expire == 0)
54   - return 0;
55   -
56   - rmtp = (struct compat_timespec __user *)restart->arg1;
57   - if (rmtp) {
58   - struct compat_timespec ct;
59   - struct timespec t;
60   -
61   - jiffies_to_timespec(expire, &t);
62   - ct.tv_sec = t.tv_sec;
63   - ct.tv_nsec = t.tv_nsec;
64   - if (copy_to_user(rmtp, &ct, sizeof(ct)))
65   - return -EFAULT;
66   - }
67   - /* The 'restart' block is already filled in */
68   - return -ERESTART_RESTARTBLOCK;
69   -}
70   -
71 43 asmlinkage long compat_sys_nanosleep(struct compat_timespec __user *rqtp,
72   - struct compat_timespec __user *rmtp)
  44 + struct compat_timespec __user *rmtp)
73 45 {
74   - struct timespec t;
75   - struct restart_block *restart;
76   - unsigned long expire;
  46 + struct timespec tu, rmt;
  47 + long ret;
77 48  
78   - if (get_compat_timespec(&t, rqtp))
  49 + if (get_compat_timespec(&tu, rqtp))
79 50 return -EFAULT;
80 51  
81   - if ((t.tv_nsec >= 1000000000L) || (t.tv_nsec < 0) || (t.tv_sec < 0))
  52 + if (!timespec_valid(&tu))
82 53 return -EINVAL;
83 54  
84   - expire = timespec_to_jiffies(&t) + (t.tv_sec || t.tv_nsec);
85   - expire = schedule_timeout_interruptible(expire);
86   - if (expire == 0)
87   - return 0;
  55 + ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL,
  56 + CLOCK_MONOTONIC);
88 57  
89   - if (rmtp) {
90   - jiffies_to_timespec(expire, &t);
91   - if (put_compat_timespec(&t, rmtp))
  58 + if (ret && rmtp) {
  59 + if (put_compat_timespec(&rmt, rmtp))
92 60 return -EFAULT;
93 61 }
94   - restart = &current_thread_info()->restart_block;
95   - restart->fn = compat_nanosleep_restart;
96   - restart->arg0 = jiffies + expire;
97   - restart->arg1 = (unsigned long) rmtp;
98   - return -ERESTART_RESTARTBLOCK;
  62 +
  63 + return ret;
99 64 }
100 65  
101 66 static inline long get_compat_itimerval(struct itimerval *o,
... ... @@ -1286,8 +1286,7 @@
1286 1286 long __sched hrtimer_nanosleep_restart(struct restart_block *restart)
1287 1287 {
1288 1288 struct hrtimer_sleeper t;
1289   - struct timespec __user *rmtp;
1290   - struct timespec tu;
  1289 + struct timespec *rmtp;
1291 1290 ktime_t time;
1292 1291  
1293 1292 restart->fn = do_no_restart_syscall;
1294 1293  
... ... @@ -1298,14 +1297,12 @@
1298 1297 if (do_nanosleep(&t, HRTIMER_MODE_ABS))
1299 1298 return 0;
1300 1299  
1301   - rmtp = (struct timespec __user *) restart->arg1;
  1300 + rmtp = (struct timespec *)restart->arg1;
1302 1301 if (rmtp) {
1303 1302 time = ktime_sub(t.timer.expires, t.timer.base->get_time());
1304 1303 if (time.tv64 <= 0)
1305 1304 return 0;
1306   - tu = ktime_to_timespec(time);
1307   - if (copy_to_user(rmtp, &tu, sizeof(tu)))
1308   - return -EFAULT;
  1305 + *rmtp = ktime_to_timespec(time);
1309 1306 }
1310 1307  
1311 1308 restart->fn = hrtimer_nanosleep_restart;
1312 1309  
... ... @@ -1314,12 +1311,11 @@
1314 1311 return -ERESTART_RESTARTBLOCK;
1315 1312 }
1316 1313  
1317   -long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp,
  1314 +long hrtimer_nanosleep(struct timespec *rqtp, struct timespec *rmtp,
1318 1315 const enum hrtimer_mode mode, const clockid_t clockid)
1319 1316 {
1320 1317 struct restart_block *restart;
1321 1318 struct hrtimer_sleeper t;
1322   - struct timespec tu;
1323 1319 ktime_t rem;
1324 1320  
1325 1321 hrtimer_init(&t.timer, clockid, mode);
... ... @@ -1335,9 +1331,7 @@
1335 1331 rem = ktime_sub(t.timer.expires, t.timer.base->get_time());
1336 1332 if (rem.tv64 <= 0)
1337 1333 return 0;
1338   - tu = ktime_to_timespec(rem);
1339   - if (copy_to_user(rmtp, &tu, sizeof(tu)))
1340   - return -EFAULT;
  1334 + *rmtp = ktime_to_timespec(rem);
1341 1335 }
1342 1336  
1343 1337 restart = &current_thread_info()->restart_block;
... ... @@ -1353,7 +1347,8 @@
1353 1347 asmlinkage long
1354 1348 sys_nanosleep(struct timespec __user *rqtp, struct timespec __user *rmtp)
1355 1349 {
1356   - struct timespec tu;
  1350 + struct timespec tu, rmt;
  1351 + int ret;
1357 1352  
1358 1353 if (copy_from_user(&tu, rqtp, sizeof(tu)))
1359 1354 return -EFAULT;
... ... @@ -1361,7 +1356,15 @@
1361 1356 if (!timespec_valid(&tu))
1362 1357 return -EINVAL;
1363 1358  
1364   - return hrtimer_nanosleep(&tu, rmtp, HRTIMER_MODE_REL, CLOCK_MONOTONIC);
  1359 + ret = hrtimer_nanosleep(&tu, rmtp ? &rmt : NULL, HRTIMER_MODE_REL,
  1360 + CLOCK_MONOTONIC);
  1361 +
  1362 + if (ret && rmtp) {
  1363 + if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
  1364 + return -EFAULT;
  1365 + }
  1366 +
  1367 + return ret;
1365 1368 }
1366 1369  
1367 1370 /*
kernel/posix-timers.c
... ... @@ -981,9 +981,20 @@
981 981 static int common_nsleep(const clockid_t which_clock, int flags,
982 982 struct timespec *tsave, struct timespec __user *rmtp)
983 983 {
984   - return hrtimer_nanosleep(tsave, rmtp, flags & TIMER_ABSTIME ?
985   - HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
986   - which_clock);
  984 + struct timespec rmt;
  985 + int ret;
  986 +
  987 + ret = hrtimer_nanosleep(tsave, rmtp ? &rmt : NULL,
  988 + flags & TIMER_ABSTIME ?
  989 + HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
  990 + which_clock);
  991 +
  992 + if (ret && rmtp) {
  993 + if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
  994 + return -EFAULT;
  995 + }
  996 +
  997 + return ret;
987 998 }
988 999  
989 1000 asmlinkage long