diff options
author | Toyo Abe <toyoa@mvista.com> | 2006-09-29 05:00:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-29 12:18:15 -0400 |
commit | 1711ef3866b0360e102327389fe4b76c849bbe83 (patch) | |
tree | b74a2cb6167840563d450859a571d6685966b771 /kernel/compat.c | |
parent | 9c4751fd0eab5b8ebbfafb28cbcc8e03b0da5933 (diff) |
[PATCH] posix-timers: Fix clock_nanosleep() doesn't return the remaining time in compatibility mode
The clock_nanosleep() function does not return the time remaining when the
sleep is interrupted by a signal.
This patch creates a new call out, compat_clock_nanosleep_restart(), which
handles returning the remaining time after a sleep is interrupted. This
patch revives clock_nanosleep_restart(). It is now accessed via the new
call out. The compat_clock_nanosleep_restart() is used for compatibility
access.
Since this is implemented in compatibility mode the normal path is
virtually unaffected - no real performance impact.
Signed-off-by: Toyo Abe <toyoa@mvista.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/compat.c')
-rw-r--r-- | kernel/compat.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/kernel/compat.c b/kernel/compat.c index 126dee9530aa..75573e5d27b0 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/security.h> | 22 | #include <linux/security.h> |
23 | #include <linux/timex.h> | 23 | #include <linux/timex.h> |
24 | #include <linux/migrate.h> | 24 | #include <linux/migrate.h> |
25 | #include <linux/posix-timers.h> | ||
25 | 26 | ||
26 | #include <asm/uaccess.h> | 27 | #include <asm/uaccess.h> |
27 | 28 | ||
@@ -601,6 +602,30 @@ long compat_sys_clock_getres(clockid_t which_clock, | |||
601 | return err; | 602 | return err; |
602 | } | 603 | } |
603 | 604 | ||
605 | static long compat_clock_nanosleep_restart(struct restart_block *restart) | ||
606 | { | ||
607 | long err; | ||
608 | mm_segment_t oldfs; | ||
609 | struct timespec tu; | ||
610 | struct compat_timespec *rmtp = (struct compat_timespec *)(restart->arg1); | ||
611 | |||
612 | restart->arg1 = (unsigned long) &tu; | ||
613 | oldfs = get_fs(); | ||
614 | set_fs(KERNEL_DS); | ||
615 | err = clock_nanosleep_restart(restart); | ||
616 | set_fs(oldfs); | ||
617 | |||
618 | if ((err == -ERESTART_RESTARTBLOCK) && rmtp && | ||
619 | put_compat_timespec(&tu, rmtp)) | ||
620 | return -EFAULT; | ||
621 | |||
622 | if (err == -ERESTART_RESTARTBLOCK) { | ||
623 | restart->fn = compat_clock_nanosleep_restart; | ||
624 | restart->arg1 = (unsigned long) rmtp; | ||
625 | } | ||
626 | return err; | ||
627 | } | ||
628 | |||
604 | long compat_sys_clock_nanosleep(clockid_t which_clock, int flags, | 629 | long compat_sys_clock_nanosleep(clockid_t which_clock, int flags, |
605 | struct compat_timespec __user *rqtp, | 630 | struct compat_timespec __user *rqtp, |
606 | struct compat_timespec __user *rmtp) | 631 | struct compat_timespec __user *rmtp) |
@@ -608,6 +633,7 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags, | |||
608 | long err; | 633 | long err; |
609 | mm_segment_t oldfs; | 634 | mm_segment_t oldfs; |
610 | struct timespec in, out; | 635 | struct timespec in, out; |
636 | struct restart_block *restart; | ||
611 | 637 | ||
612 | if (get_compat_timespec(&in, rqtp)) | 638 | if (get_compat_timespec(&in, rqtp)) |
613 | return -EFAULT; | 639 | return -EFAULT; |
@@ -618,9 +644,16 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags, | |||
618 | (struct timespec __user *) &in, | 644 | (struct timespec __user *) &in, |
619 | (struct timespec __user *) &out); | 645 | (struct timespec __user *) &out); |
620 | set_fs(oldfs); | 646 | set_fs(oldfs); |
647 | |||
621 | if ((err == -ERESTART_RESTARTBLOCK) && rmtp && | 648 | if ((err == -ERESTART_RESTARTBLOCK) && rmtp && |
622 | put_compat_timespec(&out, rmtp)) | 649 | put_compat_timespec(&out, rmtp)) |
623 | return -EFAULT; | 650 | return -EFAULT; |
651 | |||
652 | if (err == -ERESTART_RESTARTBLOCK) { | ||
653 | restart = ¤t_thread_info()->restart_block; | ||
654 | restart->fn = compat_clock_nanosleep_restart; | ||
655 | restart->arg1 = (unsigned long) rmtp; | ||
656 | } | ||
624 | return err; | 657 | return err; |
625 | } | 658 | } |
626 | 659 | ||