}
 }
 
-int posix_cpu_nsleep(const clockid_t which_clock, int flags,
-                    struct timespec *rqtp, struct timespec __user *rmtp)
+static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
+                           struct timespec *rqtp, struct itimerspec *it)
 {
-       struct restart_block *restart_block =
-           ¤t_thread_info()->restart_block;
        struct k_itimer timer;
        int error;
 
-       /*
-        * Diagnose required errors first.
-        */
-       if (CPUCLOCK_PERTHREAD(which_clock) &&
-           (CPUCLOCK_PID(which_clock) == 0 ||
-            CPUCLOCK_PID(which_clock) == current->pid))
-               return -EINVAL;
-
        /*
         * Set up a temporary timer and then wait for it to go off.
         */
        timer.it_process = current;
        if (!error) {
                static struct itimerspec zero_it;
-               struct itimerspec it = { .it_value = *rqtp,
-                                        .it_interval = {} };
+
+               memset(it, 0, sizeof *it);
+               it->it_value = *rqtp;
 
                spin_lock_irq(&timer.it_lock);
-               error = posix_cpu_timer_set(&timer, flags, &it, NULL);
+               error = posix_cpu_timer_set(&timer, flags, it, NULL);
                if (error) {
                        spin_unlock_irq(&timer.it_lock);
                        return error;
                 * We were interrupted by a signal.
                 */
                sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp);
-               posix_cpu_timer_set(&timer, 0, &zero_it, &it);
+               posix_cpu_timer_set(&timer, 0, &zero_it, it);
                spin_unlock_irq(&timer.it_lock);
 
-               if ((it.it_value.tv_sec | it.it_value.tv_nsec) == 0) {
+               if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) {
                        /*
                         * It actually did fire already.
                         */
                        return 0;
                }
 
+               error = -ERESTART_RESTARTBLOCK;
+       }
+
+       return error;
+}
+
+int posix_cpu_nsleep(const clockid_t which_clock, int flags,
+                    struct timespec *rqtp, struct timespec __user *rmtp)
+{
+       struct restart_block *restart_block =
+           ¤t_thread_info()->restart_block;
+       struct itimerspec it;
+       int error;
+
+       /*
+        * Diagnose required errors first.
+        */
+       if (CPUCLOCK_PERTHREAD(which_clock) &&
+           (CPUCLOCK_PID(which_clock) == 0 ||
+            CPUCLOCK_PID(which_clock) == current->pid))
+               return -EINVAL;
+
+       error = do_cpu_nanosleep(which_clock, flags, rqtp, &it);
+
+       if (error == -ERESTART_RESTARTBLOCK) {
+
+               if (flags & TIMER_ABSTIME)
+                       return -ERESTARTNOHAND;
                /*
-                * Report back to the user the time still remaining.
-                */
-               if (rmtp != NULL && !(flags & TIMER_ABSTIME) &&
-                   copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
+                * Report back to the user the time still remaining.
+                */
+               if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
                        return -EFAULT;
 
                restart_block->fn = posix_cpu_nsleep_restart;
-               /* Caller already set restart_block->arg1 */
                restart_block->arg0 = which_clock;
                restart_block->arg1 = (unsigned long) rmtp;
                restart_block->arg2 = rqtp->tv_sec;
                restart_block->arg3 = rqtp->tv_nsec;
-
-               error = -ERESTART_RESTARTBLOCK;
        }
-
        return error;
 }
 
        clockid_t which_clock = restart_block->arg0;
        struct timespec __user *rmtp;
        struct timespec t;
+       struct itimerspec it;
+       int error;
 
        rmtp = (struct timespec __user *) restart_block->arg1;
        t.tv_sec = restart_block->arg2;
        t.tv_nsec = restart_block->arg3;
 
        restart_block->fn = do_no_restart_syscall;
-       return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t, rmtp);
+       error = do_cpu_nanosleep(which_clock, TIMER_ABSTIME, &t, &it);
+
+       if (error == -ERESTART_RESTARTBLOCK) {
+               /*
+                * Report back to the user the time still remaining.
+                */
+               if (rmtp != NULL && copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
+                       return -EFAULT;
+
+               restart_block->fn = posix_cpu_nsleep_restart;
+               restart_block->arg0 = which_clock;
+               restart_block->arg1 = (unsigned long) rmtp;
+               restart_block->arg2 = t.tv_sec;
+               restart_block->arg3 = t.tv_nsec;
+       }
+       return error;
+
 }