diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-12-27 16:52:33 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-02-03 15:09:25 -0500 |
commit | 9d94b9e2f354f79461aa674e75b0926d0e768db6 (patch) | |
tree | 09dd0557dc4cf2442205c55c8789af7170c2631f /fs/timerfd.c | |
parent | 90caf58dad77a4021e9dade5d051756cea2a2cd7 (diff) |
switch timerfd compat syscalls to COMPAT_SYSCALL_DEFINE
... and move them over to fs/timerfd.c. Cleaner and easier
that way...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/timerfd.c')
-rw-r--r-- | fs/timerfd.c | 85 |
1 files changed, 66 insertions, 19 deletions
diff --git a/fs/timerfd.c b/fs/timerfd.c index d03822bbf190..0e606b12a59d 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/anon_inodes.h> | 22 | #include <linux/anon_inodes.h> |
23 | #include <linux/timerfd.h> | 23 | #include <linux/timerfd.h> |
24 | #include <linux/syscalls.h> | 24 | #include <linux/syscalls.h> |
25 | #include <linux/compat.h> | ||
25 | #include <linux/rcupdate.h> | 26 | #include <linux/rcupdate.h> |
26 | 27 | ||
27 | struct timerfd_ctx { | 28 | struct timerfd_ctx { |
@@ -278,21 +279,17 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags) | |||
278 | return ufd; | 279 | return ufd; |
279 | } | 280 | } |
280 | 281 | ||
281 | SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, | 282 | static int do_timerfd_settime(int ufd, int flags, |
282 | const struct itimerspec __user *, utmr, | 283 | const struct itimerspec *new, |
283 | struct itimerspec __user *, otmr) | 284 | struct itimerspec *old) |
284 | { | 285 | { |
285 | struct fd f; | 286 | struct fd f; |
286 | struct timerfd_ctx *ctx; | 287 | struct timerfd_ctx *ctx; |
287 | struct itimerspec ktmr, kotmr; | ||
288 | int ret; | 288 | int ret; |
289 | 289 | ||
290 | if (copy_from_user(&ktmr, utmr, sizeof(ktmr))) | ||
291 | return -EFAULT; | ||
292 | |||
293 | if ((flags & ~TFD_SETTIME_FLAGS) || | 290 | if ((flags & ~TFD_SETTIME_FLAGS) || |
294 | !timespec_valid(&ktmr.it_value) || | 291 | !timespec_valid(&new->it_value) || |
295 | !timespec_valid(&ktmr.it_interval)) | 292 | !timespec_valid(&new->it_interval)) |
296 | return -EINVAL; | 293 | return -EINVAL; |
297 | 294 | ||
298 | ret = timerfd_fget(ufd, &f); | 295 | ret = timerfd_fget(ufd, &f); |
@@ -323,27 +320,23 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, | |||
323 | if (ctx->expired && ctx->tintv.tv64) | 320 | if (ctx->expired && ctx->tintv.tv64) |
324 | hrtimer_forward_now(&ctx->tmr, ctx->tintv); | 321 | hrtimer_forward_now(&ctx->tmr, ctx->tintv); |
325 | 322 | ||
326 | kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); | 323 | old->it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); |
327 | kotmr.it_interval = ktime_to_timespec(ctx->tintv); | 324 | old->it_interval = ktime_to_timespec(ctx->tintv); |
328 | 325 | ||
329 | /* | 326 | /* |
330 | * Re-program the timer to the new value ... | 327 | * Re-program the timer to the new value ... |
331 | */ | 328 | */ |
332 | ret = timerfd_setup(ctx, flags, &ktmr); | 329 | ret = timerfd_setup(ctx, flags, new); |
333 | 330 | ||
334 | spin_unlock_irq(&ctx->wqh.lock); | 331 | spin_unlock_irq(&ctx->wqh.lock); |
335 | fdput(f); | 332 | fdput(f); |
336 | if (otmr && copy_to_user(otmr, &kotmr, sizeof(kotmr))) | ||
337 | return -EFAULT; | ||
338 | |||
339 | return ret; | 333 | return ret; |
340 | } | 334 | } |
341 | 335 | ||
342 | SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) | 336 | static int do_timerfd_gettime(int ufd, struct itimerspec *t) |
343 | { | 337 | { |
344 | struct fd f; | 338 | struct fd f; |
345 | struct timerfd_ctx *ctx; | 339 | struct timerfd_ctx *ctx; |
346 | struct itimerspec kotmr; | ||
347 | int ret = timerfd_fget(ufd, &f); | 340 | int ret = timerfd_fget(ufd, &f); |
348 | if (ret) | 341 | if (ret) |
349 | return ret; | 342 | return ret; |
@@ -356,11 +349,65 @@ SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) | |||
356 | hrtimer_forward_now(&ctx->tmr, ctx->tintv) - 1; | 349 | hrtimer_forward_now(&ctx->tmr, ctx->tintv) - 1; |
357 | hrtimer_restart(&ctx->tmr); | 350 | hrtimer_restart(&ctx->tmr); |
358 | } | 351 | } |
359 | kotmr.it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); | 352 | t->it_value = ktime_to_timespec(timerfd_get_remaining(ctx)); |
360 | kotmr.it_interval = ktime_to_timespec(ctx->tintv); | 353 | t->it_interval = ktime_to_timespec(ctx->tintv); |
361 | spin_unlock_irq(&ctx->wqh.lock); | 354 | spin_unlock_irq(&ctx->wqh.lock); |
362 | fdput(f); | 355 | fdput(f); |
356 | return 0; | ||
357 | } | ||
358 | |||
359 | SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, | ||
360 | const struct itimerspec __user *, utmr, | ||
361 | struct itimerspec __user *, otmr) | ||
362 | { | ||
363 | struct itimerspec new, old; | ||
364 | int ret; | ||
365 | |||
366 | if (copy_from_user(&new, utmr, sizeof(new))) | ||
367 | return -EFAULT; | ||
368 | ret = do_timerfd_settime(ufd, flags, &new, &old); | ||
369 | if (ret) | ||
370 | return ret; | ||
371 | if (otmr && copy_to_user(otmr, &old, sizeof(old))) | ||
372 | return -EFAULT; | ||
373 | |||
374 | return ret; | ||
375 | } | ||
363 | 376 | ||
377 | SYSCALL_DEFINE2(timerfd_gettime, int, ufd, struct itimerspec __user *, otmr) | ||
378 | { | ||
379 | struct itimerspec kotmr; | ||
380 | int ret = do_timerfd_gettime(ufd, &kotmr); | ||
381 | if (ret) | ||
382 | return ret; | ||
364 | return copy_to_user(otmr, &kotmr, sizeof(kotmr)) ? -EFAULT: 0; | 383 | return copy_to_user(otmr, &kotmr, sizeof(kotmr)) ? -EFAULT: 0; |
365 | } | 384 | } |
366 | 385 | ||
386 | #ifdef COMPAT | ||
387 | COMPAT_SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags, | ||
388 | const struct itimerspec __user *, utmr, | ||
389 | struct itimerspec __user *, otmr) | ||
390 | { | ||
391 | struct itimerspec new, old; | ||
392 | int ret; | ||
393 | |||
394 | if (get_compat_itimerspec(&new, utmr)) | ||
395 | return -EFAULT; | ||
396 | ret = do_timerfd_settime(ufd, flags, &new, &old); | ||
397 | if (ret) | ||
398 | return ret; | ||
399 | if (otmr && put_compat_itimerspec(otmr, &old)) | ||
400 | return -EFAULT; | ||
401 | return ret; | ||
402 | } | ||
403 | |||
404 | COMPAT_SYSCALL_DEFINE2(timerfd_gettime, int, ufd, | ||
405 | struct itimerspec __user *, otmr) | ||
406 | { | ||
407 | struct itimerspec kotmr; | ||
408 | int ret = do_timerfd_gettime(ufd, &kotmr); | ||
409 | if (ret) | ||
410 | return ret; | ||
411 | return put_compat_itimerspec(otmr, &t) ? -EFAULT: 0; | ||
412 | } | ||
413 | #endif | ||