[PATCH] __vm_enough_memory() signedness fix

We have found what seems to be a small bug in __vm_enough_memory() when
sysctl_overcommit_memory is set to OVERCOMMIT_NEVER.

When this bug occurs the systems fails to boot, with /sbin/init whining
about fork() returning ENOMEM.

We hunted down the problem to this:

The deferred update mecanism used in vm_acct_memory(), on a SMP system,
allows the vm_committed_space counter to have a negative value.

This should not be a problem since this counter is known to be inaccurate.

But in __vm_enough_memory() this counter is compared to the `allowed'
variable, which is an unsigned long. This comparison is broken since it
will consider the negative values of vm_committed_space to be huge positive
values, resulting in a memory allocation failure.

Signed-off-by: <Jean-Marc.Saffroy@ext.bull.net>
Signed-off-by: <Simon.Derr@bull.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by Simon Derr and committed by Linus Torvalds 2f60f8d3 b68e9f85

+10 -2
+5 -1
mm/mmap.c
··· 143 143 leave 3% of the size of this process for other processes */ 144 144 allowed -= current->mm->total_vm / 32; 145 145 146 - if (atomic_read(&vm_committed_space) < allowed) 146 + /* 147 + * cast `allowed' as a signed long because vm_committed_space 148 + * sometimes has a negative value 149 + */ 150 + if (atomic_read(&vm_committed_space) < (long)allowed) 147 151 return 0; 148 152 149 153 vm_unacct_memory(pages);
+5 -1
mm/nommu.c
··· 1167 1167 leave 3% of the size of this process for other processes */ 1168 1168 allowed -= current->mm->total_vm / 32; 1169 1169 1170 - if (atomic_read(&vm_committed_space) < allowed) 1170 + /* 1171 + * cast `allowed' as a signed long because vm_committed_space 1172 + * sometimes has a negative value 1173 + */ 1174 + if (atomic_read(&vm_committed_space) < (long)allowed) 1171 1175 return 0; 1172 1176 1173 1177 vm_unacct_memory(pages);