Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[pandora-kernel.git] / kernel / compat.c
index 3bae374..4a856a3 100644 (file)
@@ -42,60 +42,59 @@ int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user
 
 static long compat_nanosleep_restart(struct restart_block *restart)
 {
-       unsigned long expire = restart->arg0, now = jiffies;
        struct compat_timespec __user *rmtp;
+       struct timespec rmt;
+       mm_segment_t oldfs;
+       long ret;
 
-       /* 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;
+       restart->nanosleep.rmtp = (struct timespec __user *) &rmt;
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+       ret = hrtimer_nanosleep_restart(restart);
+       set_fs(oldfs);
 
-       rmtp = (struct compat_timespec __user *)restart->arg1;
-       if (rmtp) {
-               struct compat_timespec ct;
-               struct timespec t;
+       if (ret) {
+               rmtp = restart->nanosleep.compat_rmtp;
 
-               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)))
+               if (rmtp && put_compat_timespec(&rmt, rmtp))
                        return -EFAULT;
        }
-       /* The 'restart' block is already filled in */
-       return -ERESTART_RESTARTBLOCK;
+
+       return ret;
 }
 
 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, rmt;
+       mm_segment_t oldfs;
+       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;
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+       ret = hrtimer_nanosleep(&tu,
+                               rmtp ? (struct timespec __user *)&rmt : NULL,
+                               HRTIMER_MODE_REL, CLOCK_MONOTONIC);
+       set_fs(oldfs);
+
+       if (ret) {
+               struct restart_block *restart
+                       = &current_thread_info()->restart_block;
 
-       if (rmtp) {
-               jiffies_to_timespec(expire, &t);
-               if (put_compat_timespec(&t, rmtp))
+               restart->fn = compat_nanosleep_restart;
+               restart->nanosleep.compat_rmtp = rmtp;
+
+               if (rmtp && put_compat_timespec(&rmt, 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,
@@ -247,8 +246,8 @@ asmlinkage long compat_sys_setrlimit(unsigned int resource,
        int ret;
        mm_segment_t old_fs = get_fs ();
 
-       if (resource >= RLIM_NLIMITS) 
-               return -EINVAL; 
+       if (resource >= RLIM_NLIMITS)
+               return -EINVAL;
 
        if (!access_ok(VERIFY_READ, rlim, sizeof(*rlim)) ||
            __get_user(r.rlim_cur, &rlim->rlim_cur) ||
@@ -446,7 +445,7 @@ asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid,
        if (retval)
                return retval;
 
-       return sched_setaffinity(pid, new_mask);
+       return sched_setaffinity(pid, &new_mask);
 }
 
 asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
@@ -477,21 +476,21 @@ asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
 
 int get_compat_itimerspec(struct itimerspec *dst,
                          const struct compat_itimerspec __user *src)
-{ 
+{
        if (get_compat_timespec(&dst->it_interval, &src->it_interval) ||
            get_compat_timespec(&dst->it_value, &src->it_value))
                return -EFAULT;
        return 0;
-} 
+}
 
 int put_compat_itimerspec(struct compat_itimerspec __user *dst,
                          const struct itimerspec *src)
-{ 
+{
        if (put_compat_timespec(&src->it_interval, &dst->it_interval) ||
            put_compat_timespec(&src->it_value, &dst->it_value))
                return -EFAULT;
        return 0;
-} 
+}
 
 long compat_sys_timer_create(clockid_t which_clock,
                        struct compat_sigevent __user *timer_event_spec,
@@ -512,9 +511,9 @@ long compat_sys_timer_create(clockid_t which_clock,
 }
 
 long compat_sys_timer_settime(timer_t timer_id, int flags,
-                         struct compat_itimerspec __user *new, 
+                         struct compat_itimerspec __user *new,
                          struct compat_itimerspec __user *old)
-{ 
+{
        long err;
        mm_segment_t oldfs;
        struct itimerspec newts, oldts;
@@ -522,58 +521,58 @@ long compat_sys_timer_settime(timer_t timer_id, int flags,
        if (!new)
                return -EINVAL;
        if (get_compat_itimerspec(&newts, new))
-               return -EFAULT; 
+               return -EFAULT;
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        err = sys_timer_settime(timer_id, flags,
                                (struct itimerspec __user *) &newts,
                                (struct itimerspec __user *) &oldts);
-       set_fs(oldfs); 
+       set_fs(oldfs);
        if (!err && old && put_compat_itimerspec(old, &oldts))
                return -EFAULT;
        return err;
-} 
+}
 
 long compat_sys_timer_gettime(timer_t timer_id,
                struct compat_itimerspec __user *setting)
-{ 
+{
        long err;
        mm_segment_t oldfs;
-       struct itimerspec ts; 
+       struct itimerspec ts;
 
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        err = sys_timer_gettime(timer_id,
-                               (struct itimerspec __user *) &ts); 
-       set_fs(oldfs); 
+                               (struct itimerspec __user *) &ts);
+       set_fs(oldfs);
        if (!err && put_compat_itimerspec(setting, &ts))
                return -EFAULT;
        return err;
-} 
+}
 
 long compat_sys_clock_settime(clockid_t which_clock,
                struct compat_timespec __user *tp)
 {
        long err;
        mm_segment_t oldfs;
-       struct timespec ts; 
+       struct timespec ts;
 
        if (get_compat_timespec(&ts, tp))
-               return -EFAULT; 
+               return -EFAULT;
        oldfs = get_fs();
-       set_fs(KERNEL_DS);      
+       set_fs(KERNEL_DS);
        err = sys_clock_settime(which_clock,
                                (struct timespec __user *) &ts);
        set_fs(oldfs);
        return err;
-} 
+}
 
 long compat_sys_clock_gettime(clockid_t which_clock,
                struct compat_timespec __user *tp)
 {
        long err;
        mm_segment_t oldfs;
-       struct timespec ts; 
+       struct timespec ts;
 
        oldfs = get_fs();
        set_fs(KERNEL_DS);
@@ -581,16 +580,16 @@ long compat_sys_clock_gettime(clockid_t which_clock,
                                (struct timespec __user *) &ts);
        set_fs(oldfs);
        if (!err && put_compat_timespec(&ts, tp))
-               return -EFAULT; 
+               return -EFAULT;
        return err;
-} 
+}
 
 long compat_sys_clock_getres(clockid_t which_clock,
                struct compat_timespec __user *tp)
 {
        long err;
        mm_segment_t oldfs;
-       struct timespec ts; 
+       struct timespec ts;
 
        oldfs = get_fs();
        set_fs(KERNEL_DS);
@@ -598,18 +597,18 @@ long compat_sys_clock_getres(clockid_t which_clock,
                               (struct timespec __user *) &ts);
        set_fs(oldfs);
        if (!err && tp && put_compat_timespec(&ts, tp))
-               return -EFAULT; 
+               return -EFAULT;
        return err;
-} 
+}
 
 static long compat_clock_nanosleep_restart(struct restart_block *restart)
 {
        long err;
        mm_segment_t oldfs;
        struct timespec tu;
-       struct compat_timespec *rmtp = (struct compat_timespec *)(restart->arg1);
+       struct compat_timespec *rmtp = restart->nanosleep.compat_rmtp;
 
-       restart->arg1 = (unsigned long) &tu;
+       restart->nanosleep.rmtp = (struct timespec __user *) &tu;
        oldfs = get_fs();
        set_fs(KERNEL_DS);
        err = clock_nanosleep_restart(restart);
@@ -621,7 +620,7 @@ static long compat_clock_nanosleep_restart(struct restart_block *restart)
 
        if (err == -ERESTART_RESTARTBLOCK) {
                restart->fn = compat_clock_nanosleep_restart;
-               restart->arg1 = (unsigned long) rmtp;
+               restart->nanosleep.compat_rmtp = rmtp;
        }
        return err;
 }
@@ -632,10 +631,10 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
 {
        long err;
        mm_segment_t oldfs;
-       struct timespec in, out; 
+       struct timespec in, out;
        struct restart_block *restart;
 
-       if (get_compat_timespec(&in, rqtp)) 
+       if (get_compat_timespec(&in, rqtp))
                return -EFAULT;
 
        oldfs = get_fs();
@@ -652,10 +651,10 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
        if (err == -ERESTART_RESTARTBLOCK) {
                restart = &current_thread_info()->restart_block;
                restart->fn = compat_clock_nanosleep_restart;
-               restart->arg1 = (unsigned long) rmtp;
+               restart->nanosleep.compat_rmtp = rmtp;
        }
-       return err;     
-} 
+       return err;
+}
 
 /*
  * We currently only need the following fields from the sigevent
@@ -899,7 +898,7 @@ asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
+       set_restore_sigmask();
        return -ERESTARTNOHAND;
 }
 #endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
@@ -1081,4 +1080,3 @@ compat_sys_sysinfo(struct compat_sysinfo __user *info)
 
        return 0;
 }
-