Commit 58f9b52ee8712283f7ffedb661df678c61e88a91
Exists in
master
and in
39 other branches
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); |
kernel/compat.c
... | ... | @@ -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 = ¤t_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, |
kernel/hrtimer.c
... | ... | @@ -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 = ¤t_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 |