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) ...@@ -1024,6 +1024,9 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm)
} }
#endif #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 /* __KERNEL__ */
#endif #endif
...@@ -412,92 +412,54 @@ compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, ...@@ -412,92 +412,54 @@ compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options,
} }
} }
/* static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
* for maximum compatability, we allow programs to use a single (compat) unsigned len, cpumask_t *new_mask)
* 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)
{ {
cpumask_t kern_mask; unsigned long *k;
mm_segment_t old_fs;
int ret;
if (USE_COMPAT_ULONG_CPUMASK) { if (len < sizeof(cpumask_t))
compat_ulong_t user_mask; memset(new_mask, 0, sizeof(cpumask_t));
else if (len > sizeof(cpumask_t))
len = sizeof(cpumask_t);
if (len < sizeof(user_mask)) k = cpus_addr(*new_mask);
return -EINVAL; return compat_get_bitmap(k, user_mask_ptr, len * 8);
}
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(kern_mask); asmlinkage long compat_sys_sched_setaffinity(compat_pid_t pid,
ret = compat_get_bitmap(k, user_mask_ptr, unsigned int len,
sizeof(kern_mask) * BITS_PER_LONG); compat_ulong_t __user *user_mask_ptr)
if (ret) {
return ret; cpumask_t new_mask;
} int retval;
old_fs = get_fs(); retval = compat_get_user_cpu_mask(user_mask_ptr, len, &new_mask);
set_fs(KERNEL_DS); if (retval)
ret = sys_sched_setaffinity(pid, return retval;
sizeof(kern_mask),
(unsigned long __user *) &kern_mask);
set_fs(old_fs);
return ret; return sched_setaffinity(pid, new_mask);
} }
asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len, asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len,
compat_ulong_t __user *user_mask_ptr) compat_ulong_t __user *user_mask_ptr)
{ {
cpumask_t kern_mask;
mm_segment_t old_fs;
int ret; int ret;
cpumask_t mask;
unsigned long *k;
if (len < (USE_COMPAT_ULONG_CPUMASK ? sizeof(compat_ulong_t) if (len < sizeof(cpumask_t))
: sizeof(kern_mask)))
return -EINVAL; return -EINVAL;
old_fs = get_fs(); ret = sched_getaffinity(pid, &mask);
set_fs(KERNEL_DS);
ret = sys_sched_getaffinity(pid,
sizeof(kern_mask),
(unsigned long __user *) &kern_mask);
set_fs(old_fs);
if (ret < 0) if (ret < 0)
return ret; return ret;
if (USE_COMPAT_ULONG_CPUMASK) { k = cpus_addr(mask);
if (put_user(&cpus_addr(kern_mask)[0], user_mask_ptr)) ret = compat_put_bitmap(user_mask_ptr, k, sizeof(cpumask_t) * 8);
return -EFAULT; if (ret)
ret = sizeof(compat_ulong_t); return ret;
} 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);
}
return ret; return sizeof(cpumask_t);
} }
static int get_compat_itimerspec(struct itimerspec *dst, 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) ...@@ -3362,33 +3362,10 @@ asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param __user *param)
return retval; return retval;
} }
static int get_user_cpu_mask(unsigned long __user *user_mask_ptr, unsigned len, long sched_setaffinity(pid_t pid, cpumask_t new_mask)
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;
task_t *p; task_t *p;
int retval;
retval = get_user_cpu_mask(user_mask_ptr, len, &new_mask);
if (retval)
return retval;
lock_cpu_hotplug(); lock_cpu_hotplug();
read_lock(&tasklist_lock); read_lock(&tasklist_lock);
...@@ -3421,6 +3398,36 @@ asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len, ...@@ -3421,6 +3398,36 @@ asmlinkage long sys_sched_setaffinity(pid_t pid, unsigned int len,
return retval; 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 * Represents all cpu's present in the system
* In systems capable of hotplug, this map could dynamically grow * In systems capable of hotplug, this map could dynamically grow
...@@ -3436,24 +3443,11 @@ cpumask_t cpu_online_map = CPU_MASK_ALL; ...@@ -3436,24 +3443,11 @@ cpumask_t cpu_online_map = CPU_MASK_ALL;
cpumask_t cpu_possible_map = CPU_MASK_ALL; cpumask_t cpu_possible_map = CPU_MASK_ALL;
#endif #endif
/** long sched_getaffinity(pid_t pid, cpumask_t *mask)
* 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)
{ {
unsigned int real_len;
cpumask_t mask;
int retval; int retval;
task_t *p; task_t *p;
real_len = sizeof(mask);
if (len < real_len)
return -EINVAL;
lock_cpu_hotplug(); lock_cpu_hotplug();
read_lock(&tasklist_lock); read_lock(&tasklist_lock);
...@@ -3463,16 +3457,40 @@ asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len, ...@@ -3463,16 +3457,40 @@ asmlinkage long sys_sched_getaffinity(pid_t pid, unsigned int len,
goto out_unlock; goto out_unlock;
retval = 0; retval = 0;
cpus_and(mask, p->cpus_allowed, cpu_possible_map); cpus_and(*mask, p->cpus_allowed, cpu_possible_map);
out_unlock: out_unlock:
read_unlock(&tasklist_lock); read_unlock(&tasklist_lock);
unlock_cpu_hotplug(); unlock_cpu_hotplug();
if (retval) if (retval)
return 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 -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