cpumask: reduce cpumask_size
PATCH 5/5 cpumask: reduce cpumask_size
Now we're sure noone is using old cpumask operators, nor *cpumask, we can allocate less bits safely. This reduces the memory usage of off-stack cpumasks when CONFIG_CPUMASK_OFFSTACK=y but we don't have NR_CPUS actual cpus.
--- include/linux/cpumask.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
include/linux/cpumask.h +2 -4
@@ -1014,13 +1014,11 @@ static inline int cpulist_parse(const ch/** * cpumask_size - size to allocate for a 'struct cpumask' in bytes * -* This will eventually be a runtime variable, depending on nr_cpu_ids. +* This can be a runtime variable, depending on nr_cpu_ids. */ static inline size_t cpumask_size (void ) { -/* FIXME: Once all cpumask assignments are eliminated, this -* can be nr_cpumask_bits */ -return BITS_TO_LONGS (NR_CPUS ) *sizeof (long ); +return BITS_TO_LONGS (nr_cpumask_bits) *sizeof (long ); }/*
Quoted 4 lines
Now we're sure noone is using old cpumask operators, nor *cpumask, we can allocate less bits safely. This reduces the memory usage of off-stack cpumasks when
CONFIG_CPUMASK_OFFSTACK=ybut we don't haveNR_CPUSactual cpus.
I have to say I'm sorry. Probably I broke your assumption. If this patch applied, we reintroduce exposing nr_cpu_ids issue and break libnuma again. I think following change is necessary too.
Or, Am I missing something?
==================================================================
kernel/compat.c +2 -1
@@ -506,7 +506,8 @@ asmlinkage long compat_sys_sched_getaffinity(compat_pid_t pid, unsigned int len, ret =sched_getaffinity (pid, mask);if (ret ==0 ) { -size_t retlen =min_t (size_t, len,cpumask_size ()); +size_t retlen =min_t (size_t, len, +BITS_TO_LONGS (NR_CPUS ) *sizeof (long ));if (compat_put_bitmap (user_mask_ptr,cpumask_bits (mask), retlen *8 )) ret = -EFAULT ;
kernel/sched.c +2 -1
@@ -4823,7 +4823,9 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, ret =sched_getaffinity (pid, mask);if (ret ==0 ) { -size_t retlen =min_t (size_t, len,cpumask_size ()); +size_t retlen =min_t (size_t, len, +BITS_TO_LONGS (NR_CPUS ) *sizeof (long ));
Quoted 29 lines
Signed-off-by Rusty Russell <[email protected]>Cc Arnd Bergmann <[email protected]>Cc KOSAKI Motohiro <[email protected]>Cc Mike Travis <[email protected]>--- include/linux/cpumask.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)include/linux/cpumask.h +2
-4@@ -1014,13 +1014,11 @@ static inline int cpulist_parse(const ch/** * cpumask_size - size to allocate for a 'struct cpumask' in bytes * -* This will eventually be a runtime variable, depending on nr_cpu_ids. +* This can be a runtime variable, depending on nr_cpu_ids. */ static inline size_t cpumask_size (void ) { -/* FIXME: Once all cpumask assignments are eliminated, this -* can be nr_cpumask_bits */ -return BITS_TO_LONGS (NR_CPUS ) *sizeof (long ); +return BITS_TO_LONGS (nr_cpumask_bits) *sizeof (long ); }/*
Quoted 10 lines · KOSAKI Motohiro
Quoted 4 lines
Now we're sure noone is using old cpumask operators, nor *cpumask, we can allocate less bits safely. This reduces the memory usage of off-stack cpumasks when
CONFIG_CPUMASK_OFFSTACK=ybut we don't haveNR_CPUSactual cpus.I have to say I'm sorry. Probably I broke your assumption. If this patch applied, we reintroduce exposing
nr_cpu_idsissue and break libnuma again. I think following change is necessary too.Or, Am I missing something?
I cc'd you because I remembered you being involved in that libnuma issue and couldn't remember the details.
Unfortunately, this solution doesn't work:
kernel/sched.c SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, · line 4828
Quoted 12 lines
kernel/sched.c +2
-1@@ -4823,7 +4823,9 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, ret =sched_getaffinity (pid, mask);if (ret ==0 ) { -size_t retlen =min_t (size_t, len,cpumask_size ()); +size_t retlen =min_t (size_t, len, +BITS_TO_LONGS (NR_CPUS ) *sizeof (long ));
Since mask is a cpumask_var_t, only cpumask_size() is allocated. We can't copy NR_CPUS bits.
But I think it's OK, anyway. libnuma is broken because it gets upset if the number of cpus it reads from /sys/.../cpumap is more than the cpumask size returned from sys_sched_getaffinity.
Currently, getaffinity returns cpumask_size() (ie. based on NR_CPUS), and the printing routines use nr_cpumask_bits (ie. based on NR_CPUS for !CPUMASK_OFFSTACK, nr_cpu_ids for CPUMASK_OFFSTACK).
(libnuma is OK on CONFIG_CPUMASK_OFFSTACK=y because the sysfs output is *shorter* than expected. I checked the code).
With this patch, cpumask_size() becomes based on nr_cpumask_bits, so both getaffinity and sysfs are using the same basis.
Do you agree?
Rusty.
Quoted 23 lines · KOSAKI Motohiro
Quoted 10 lines
Quoted 4 lines
Now we're sure noone is using old cpumask operators, nor *cpumask, we can allocate less bits safely. This reduces the memory usage of off-stack cpumasks when
CONFIG_CPUMASK_OFFSTACK=ybut we don't haveNR_CPUSactual cpus.I have to say I'm sorry. Probably I broke your assumption. If this patch applied, we reintroduce exposing
nr_cpu_idsissue and break libnuma again. I think following change is necessary too.Or, Am I missing something?
I cc'd you because I remembered you being involved in that libnuma issue and couldn't remember the details.
Unfortunately, this solution doesn't work:
Quoted 6 lines
kernel/sched.c +0
-0@@ -4823,7 +4823,9 @@ SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len,
Quoted 9 lines
kernel/sched.c SYSCALL_DEFINE3(sched_getaffinity, pid_t, pid, unsigned int, len, · line 4828
Quoted 6 lines
kernel/sched.c +2
-1ret =sched_getaffinity (pid, mask);if (ret ==0 ) { -size_t retlen =min_t (size_t, len,cpumask_size ()); +size_t retlen =min_t (size_t, len, +BITS_TO_LONGS (NR_CPUS ) *sizeof (long ));Since mask is a
cpumask_var_t, onlycpumask_size()is allocated. We can't copyNR_CPUSbits.
Ahh, yes. It's purely broken.
Quoted 8 lines
But I think it's OK, anyway. libnuma is broken because it gets upset if the number of cpus it reads from
/sys/.../cpumapis more than the cpumask size returned fromsys_sched_getaffinity.Currently, getaffinity returns
cpumask_size()(ie. based onNR_CPUS), and the printing routines usenr_cpumask_bits(ie. based onNR_CPUSfor !CPUMASK_OFFSTACK,nr_cpu_idsforCPUMASK_OFFSTACK).
Quoted 7 lines
(libnuma is OK on
CONFIG_CPUMASK_OFFSTACK=ybecause the sysfs output is *shorter* than expected. I checked the code).With this patch,
cpumask_size()becomes based onnr_cpumask_bits, so both getaffinity and sysfs are using the same basis.Do you agree?
Sure. I agree I missed. Thank you for very kindful explanation!