Commit 2d3399ab authored by Anton Blanchard's avatar Anton Blanchard Committed by Linus Torvalds

[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: default avatarAnton Blanchard <anton@samba.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b48e213e
......@@ -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
......@@ -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,
......
......@@ -3362,33 +3362,10 @@ asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param __user *param)
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 @@ asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
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);
}
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment