fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / kernel / compat.c
index 126dee9..e697c1c 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/security.h>
 #include <linux/timex.h>
 #include <linux/migrate.h>
+#include <linux/posix-timers.h>
 
 #include <asm/uaccess.h>
 
@@ -601,6 +602,30 @@ long compat_sys_clock_getres(clockid_t which_clock,
        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);
+
+       restart->arg1 = (unsigned long) &tu;
+       oldfs = get_fs();
+       set_fs(KERNEL_DS);
+       err = clock_nanosleep_restart(restart);
+       set_fs(oldfs);
+
+       if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
+           put_compat_timespec(&tu, rmtp))
+               return -EFAULT;
+
+       if (err == -ERESTART_RESTARTBLOCK) {
+               restart->fn = compat_clock_nanosleep_restart;
+               restart->arg1 = (unsigned long) rmtp;
+       }
+       return err;
+}
+
 long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
                            struct compat_timespec __user *rqtp,
                            struct compat_timespec __user *rmtp)
@@ -608,6 +633,7 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
        long err;
        mm_segment_t oldfs;
        struct timespec in, out; 
+       struct restart_block *restart;
 
        if (get_compat_timespec(&in, rqtp)) 
                return -EFAULT;
@@ -618,9 +644,16 @@ long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
                                  (struct timespec __user *) &in,
                                  (struct timespec __user *) &out);
        set_fs(oldfs);
+
        if ((err == -ERESTART_RESTARTBLOCK) && rmtp &&
            put_compat_timespec(&out, rmtp))
                return -EFAULT;
+
+       if (err == -ERESTART_RESTARTBLOCK) {
+               restart = &current_thread_info()->restart_block;
+               restart->fn = compat_clock_nanosleep_restart;
+               restart->arg1 = (unsigned long) rmtp;
+       }
        return err;     
 } 
 
@@ -645,7 +678,7 @@ int get_compat_sigevent(struct sigevent *event,
                ? -EFAULT : 0;
 }
 
-long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask,
+long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
                       unsigned long bitmap_size)
 {
        int i, j;
@@ -813,7 +846,7 @@ asmlinkage long compat_sys_time(compat_time_t __user * tloc)
        compat_time_t i;
        struct timeval tv;
 
-       do_gettimeofday(&tv);
+       vx_gettimeofday(&tv);
        i = tv.tv_sec;
 
        if (tloc) {
@@ -837,7 +870,7 @@ asmlinkage long compat_sys_stime(compat_time_t __user *tptr)
        if (err)
                return err;
 
-       do_settimeofday(&tv);
+       vx_settimeofday(&tv);
        return 0;
 }
 
@@ -949,4 +982,37 @@ asmlinkage long compat_sys_move_pages(pid_t pid, unsigned long nr_pages,
        }
        return sys_move_pages(pid, nr_pages, pages, nodes, status, flags);
 }
+
+asmlinkage long compat_sys_migrate_pages(compat_pid_t pid,
+                       compat_ulong_t maxnode,
+                       const compat_ulong_t __user *old_nodes,
+                       const compat_ulong_t __user *new_nodes)
+{
+       unsigned long __user *old = NULL;
+       unsigned long __user *new = NULL;
+       nodemask_t tmp_mask;
+       unsigned long nr_bits;
+       unsigned long size;
+
+       nr_bits = min_t(unsigned long, maxnode - 1, MAX_NUMNODES);
+       size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
+       if (old_nodes) {
+               if (compat_get_bitmap(nodes_addr(tmp_mask), old_nodes, nr_bits))
+                       return -EFAULT;
+               old = compat_alloc_user_space(new_nodes ? size * 2 : size);
+               if (new_nodes)
+                       new = old + size / sizeof(unsigned long);
+               if (copy_to_user(old, nodes_addr(tmp_mask), size))
+                       return -EFAULT;
+       }
+       if (new_nodes) {
+               if (compat_get_bitmap(nodes_addr(tmp_mask), new_nodes, nr_bits))
+                       return -EFAULT;
+               if (new == NULL)
+                       new = compat_alloc_user_space(size);
+               if (copy_to_user(new, nodes_addr(tmp_mask), size))
+                       return -EFAULT;
+       }
+       return sys_migrate_pages(pid, nr_bits + 1, old, new);
+}
 #endif