summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2004-09-13 00:05:18 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-09-13 00:05:18 -0700
commit2d3399ab54c9763fcba314d0b33ab82e1580d7aa (patch)
treeca03be5ae2aa85daed645aa65bf4d402b0ff51f4
parentb48e213e8d730e898cf0b3945ecaf21185f27fee (diff)
[PATCH] Clean up compat sched affinity syscalls
Remove the set_fs hack in the compat affinity calls. Create sched_getaffinity and sched_setaffinity helper functions that both the native and compat affinity syscalls use. Also make the compat functions match what the native ones are doing now, setaffinity calls succeed no matter what length the bitmask is, but getaffinity calls must pass in bitmasks at least as long as the kernel type. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/linux/sched.h3
-rw-r--r--kernel/compat.c96
-rw-r--r--kernel/sched.c102
3 files changed, 92 insertions, 109 deletions
diff --git a/include/linux/sched.h b/include/linux/sched.h
index b73710a9ac12..f5d4b9cae523 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1024,6 +1024,9 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm)
}
#endif
+extern long sched_setaffinity(pid_t pid, cpumask_t new_mask);
+extern long sched_getaffinity(pid_t pid, cpumask_t *mask);
+
#endif /* __KERNEL__ */
#endif
diff --git a/kernel/compat.c b/kernel/compat.c
index 4cc18476315c..9f3f23fd2788 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -412,92 +412,54 @@ compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options,
}
}
-/*
- * for maximum compatability, we allow programs to use a single (compat)
- * unsigned long bitmask if all cpus will fit. If not, you have to have
- * at least the kernel size available.
- */
-#define USE_COMPAT_ULONG_CPUMASK (NR_CPUS <= BITS_PER_COMPAT_LONG)
-
-asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid,
- unsigned int len,
- compat_ulong_t __user *user_mask_ptr)
+static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
+ unsigned len, cpumask_t *new_mask)
{
- cpumask_t kern_mask;
- mm_segment_t old_fs;
- int ret;
+ unsigned long *k;
- if (USE_COMPAT_ULONG_CPUMASK) {
- compat_ulong_t user_mask;
+ if (len < sizeof(cpumask_t))
+ memset(new_mask, 0, sizeof(cpumask_t));
+ else if (len > sizeof(cpumask_t))
+ len = sizeof(cpumask_t);
- if (len < sizeof(user_mask))
- return -EINVAL;
-
- if (get_user(user_mask, user_mask_ptr))
- return -EFAULT;
-
- cpus_addr(kern_mask)[0] = user_mask;
- } else {
- unsigned long *k;
-
- if (len < sizeof(kern_mask))
- return -EINVAL;
+ k = cpus_addr(*new_mask);
+ return compat_get_bitmap(k, user_mask_ptr, len * 8);
+}
- k = cpus_addr(kern_mask);
- ret = compat_get_bitmap(k, user_mask_ptr,
- sizeof(kern_mask) * BITS_PER_LONG);
- if (ret)
- return ret;
- }
+asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid,
+ unsigned int len,
+ compat_ulong_t __user *user_mask_ptr)
+{
+ cpumask_t new_mask;
+ int retval;
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- ret = sys_sched_setaffinity(pid,
- sizeof(kern_mask),
- (unsigned long __user *) &kern_mask);
- set_fs(old_fs);
+ retval = compat_get_user_cpu_mask(user_mask_ptr, len, &new_mask);
+ if (retval)
+ return retval;
- return ret;
+ return sched_setaffinity(pid, new_mask);
}
asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
compat_ulong_t __user *user_mask_ptr)
{
- cpumask_t kern_mask;
- mm_segment_t old_fs;
int ret;
+ cpumask_t mask;
+ unsigned long *k;
- if (len < (USE_COMPAT_ULONG_CPUMASK ? sizeof(compat_ulong_t)
- : sizeof(kern_mask)))
+ if (len < sizeof(cpumask_t))
return -EINVAL;
- old_fs = get_fs();
- set_fs(KERNEL_DS);
- ret = sys_sched_getaffinity(pid,
- sizeof(kern_mask),
- (unsigned long __user *) &kern_mask);
- set_fs(old_fs);
-
+ ret = sched_getaffinity(pid, &mask);
if (ret < 0)
return ret;
- if (USE_COMPAT_ULONG_CPUMASK) {
- if (put_user(&cpus_addr(kern_mask)[0], user_mask_ptr))
- return -EFAULT;
- ret = sizeof(compat_ulong_t);
- } else {
- unsigned long *k;
-
- k = cpus_addr(kern_mask);
- ret = compat_put_bitmap(user_mask_ptr, k,
- sizeof(kern_mask) * BITS_PER_LONG);
- if (ret)
- return ret;
-
- ret = sizeof(kern_mask);
- }
+ k = cpus_addr(mask);
+ ret = compat_put_bitmap(user_mask_ptr, k, sizeof(cpumask_t) * 8);
+ if (ret)
+ return ret;
- return ret;
+ return sizeof(cpumask_t);
}
static int get_compat_itimerspec(struct itimerspec *dst,
diff --git a/kernel/sched.c b/kernel/sched.c
index 7dd6c27f6094..3de761b2b262 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -3362,33 +3362,10 @@ out_unlock:
return retval;
}
-static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len,
- cpumask_t *new_mask)
-{
- if (len < sizeof(cpumask_t)) {
- memset(new_mask, 0, sizeof(cpumask_t));
- } else if (len > sizeof(cpumask_t)) {
- len = sizeof(cpumask_t);
- }
- return copy_from_user(new_mask, user_mask_ptr, len) ? -EFAULT : 0;
-}
-
-/**
- * sys_sched_setaffinity - set the cpu affinity of a process
- * @pid: pid of the process
- * @len: length in bytes of the bitmask pointed to by user_mask_ptr
- * @user_mask_ptr: user-space pointer to the new cpu mask
- */
-asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
- unsigned long __user *user_mask_ptr)
+long sched_setaffinity(pid_t pid, cpumask_t new_mask)
{
- cpumask_t new_mask;
- int retval;
task_t *p;
-
- retval = get_user_cpu_mask(user_mask_ptr, len, &new_mask);
- if (retval)
- return retval;
+ int retval;
lock_cpu_hotplug();
read_lock(&tasklist_lock);
@@ -3421,6 +3398,36 @@ out_unlock:
return retval;
}
+static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len,
+ cpumask_t *new_mask)
+{
+ if (len < sizeof(cpumask_t)) {
+ memset(new_mask, 0, sizeof(cpumask_t));
+ } else if (len > sizeof(cpumask_t)) {
+ len = sizeof(cpumask_t);
+ }
+ return copy_from_user(new_mask, user_mask_ptr, len) ? -EFAULT : 0;
+}
+
+/**
+ * sys_sched_setaffinity - set the cpu affinity of a process
+ * @pid: pid of the process
+ * @len: length in bytes of the bitmask pointed to by user_mask_ptr
+ * @user_mask_ptr: user-space pointer to the new cpu mask
+ */
+asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
+ unsigned long __user *user_mask_ptr)
+{
+ cpumask_t new_mask;
+ int retval;
+
+ retval = get_user_cpu_mask(user_mask_ptr, len, &new_mask);
+ if (retval)
+ return retval;
+
+ return sched_setaffinity(pid, new_mask);
+}
+
/*
* Represents all cpu's present in the system
* In systems capable of hotplug, this map could dynamically grow
@@ -3436,24 +3443,11 @@ cpumask_t cpu_online_map = CPU_MASK_ALL;
cpumask_t cpu_possible_map = CPU_MASK_ALL;
#endif
-/**
- * sys_sched_getaffinity - get the cpu affinity of a process
- * @pid: pid of the process
- * @len: length in bytes of the bitmask pointed to by user_mask_ptr
- * @user_mask_ptr: user-space pointer to hold the current cpu mask
- */
-asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
- unsigned long __user *user_mask_ptr)
+long sched_getaffinity(pid_t pid, cpumask_t *mask)
{
- unsigned int real_len;
- cpumask_t mask;
int retval;
task_t *p;
- real_len = sizeof(mask);
- if (len < real_len)
- return -EINVAL;
-
lock_cpu_hotplug();
read_lock(&tasklist_lock);
@@ -3463,16 +3457,40 @@ asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
goto out_unlock;
retval = 0;
- cpus_and(mask, p->cpus_allowed, cpu_possible_map);
+ cpus_and(*mask, p->cpus_allowed, cpu_possible_map);
out_unlock:
read_unlock(&tasklist_lock);
unlock_cpu_hotplug();
if (retval)
return retval;
- if (copy_to_user(user_mask_ptr, &mask, real_len))
+
+ return 0;
+}
+
+/**
+ * sys_sched_getaffinity - get the cpu affinity of a process
+ * @pid: pid of the process
+ * @len: length in bytes of the bitmask pointed to by user_mask_ptr
+ * @user_mask_ptr: user-space pointer to hold the current cpu mask
+ */
+asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
+ unsigned long __user *user_mask_ptr)
+{
+ int ret;
+ cpumask_t mask;
+
+ if (len < sizeof(cpumask_t))
+ return -EINVAL;
+
+ ret = sched_getaffinity(pid, &mask);
+ if (ret < 0)
+ return ret;
+
+ if (copy_to_user(user_mask_ptr, &mask, sizeof(cpumask_t)))
return -EFAULT;
- return real_len;
+
+ return sizeof(cpumask_t);
}
/**