linux/include
Paul Jackson 4247bdc600 [PATCH] cpuset semaphore depth check deadlock fix
The cpusets-formalize-intermediate-gfp_kernel-containment patch
has a deadlock problem.

This patch was part of a set of four patches to make more
extensive use of the cpuset 'mem_exclusive' attribute to
manage kernel GFP_KERNEL memory allocations and to constrain
the out-of-memory (oom) killer.

A task that is changing cpusets in particular ways on a system
when it is very short of free memory could double trip over
the global cpuset_sem semaphore (get the lock and then deadlock
trying to get it again).

The second attempt to get cpuset_sem would be in the routine
cpuset_zone_allowed().  This was discovered by code inspection.
I can not reproduce the problem except with an artifically
hacked kernel and a specialized stress test.

In real life you cannot hit this unless you are manipulating
cpusets, and are very unlikely to hit it unless you are rapidly
modifying cpusets on a memory tight system.  Even then it would
be a rare occurence.

If you did hit it, the task double tripping over cpuset_sem
would deadlock in the kernel, and any other task also trying
to manipulate cpusets would deadlock there too, on cpuset_sem.
Your batch manager would be wedged solid (if it was cpuset
savvy), but classic Unix shells and utilities would work well
enough to reboot the system.

The unusual condition that led to this bug is that unlike most
semaphores, cpuset_sem _can_ be acquired while in the page
allocation code, when __alloc_pages() calls cpuset_zone_allowed.
So it easy to mistakenly perform the following sequence:
  1) task makes system call to alter a cpuset
  2) take cpuset_sem
  3) try to allocate memory
  4) memory allocator, via cpuset_zone_allowed, trys to take cpuset_sem
  5) deadlock

The reason that this is not a serious bug for most users
is that almost all calls to allocate memory don't require
taking cpuset_sem.  Only some code paths off the beaten
track require taking cpuset_sem -- which is good.  Taking
a global semaphore on the main code path for allocating
memory would not scale well.

This patch fixes this deadlock by wrapping the up() and down()
calls on cpuset_sem in kernel/cpuset.c with code that tracks
the nesting depth of the current task on that semaphore, and
only does the real down() if the task doesn't hold the lock
already, and only does the real up() if the nesting depth
(number of unmatched downs) is exactly one.

The previous required use of refresh_mems(), anytime that
the cpuset_sem semaphore was acquired and the code executed
while holding that semaphore might try to allocate memory, is
no longer required.  Two refresh_mems() calls were removed
thanks to this.  This is a good change, as failing to get
all the necessary refresh_mems() calls placed was a primary
source of bugs in this cpuset code.  The only remaining call
to refresh_mems() is made while doing a memory allocation,
if certain task memory placement data needs to be updated
from its cpuset, due to the cpuset having been changed behind
the tasks back.

Signed-off-by: Paul Jackson <pj@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-09-10 10:06:21 -07:00
..
acpi [ACPI] ACPICA 20050902 2005-09-03 00:15:11 -04:00
asm-alpha [PATCH] spinlock consolidation 2005-09-10 10:06:21 -07:00
asm-arm [PATCH] spinlock consolidation 2005-09-10 10:06:21 -07:00
asm-arm26 [PATCH] Clean up struct flock64 definitions 2005-09-07 16:57:38 -07:00
asm-cris [PATCH] Clean up struct flock64 definitions 2005-09-07 16:57:38 -07:00
asm-frv [PATCH] Clean up struct flock64 definitions 2005-09-07 16:57:38 -07:00
asm-generic [PATCH] Make sparc64 use setup-res.c 2005-09-08 14:57:25 -07:00
asm-h8300 [PATCH] Clean up struct flock64 definitions 2005-09-07 16:57:38 -07:00
asm-i386 [PATCH] spinlock consolidation 2005-09-10 10:06:21 -07:00
asm-ia64 [PATCH] spinlock consolidation 2005-09-10 10:06:21 -07:00
asm-m32r [PATCH] spinlock consolidation 2005-09-10 10:06:21 -07:00
asm-m68k [PATCH] Clean up struct flock64 definitions 2005-09-07 16:57:38 -07:00
asm-m68knommu [PATCH] m68knommu: include ColdFire 523x processor register definitions 2005-09-08 17:27:37 -07:00
asm-mips [PATCH] spinlock consolidation 2005-09-10 10:06:21 -07:00
asm-parisc [PATCH] spinlock consolidation 2005-09-10 10:06:21 -07:00
asm-powerpc [PATCH] powerpc: Fix __power64__ typos that should be __powerpc64__ 2005-09-09 22:11:35 +10:00
asm-ppc [PATCH] spinlock consolidation 2005-09-10 10:06:21 -07:00
asm-ppc64 [PATCH] spinlock consolidation 2005-09-10 10:06:21 -07:00
asm-s390 [PATCH] spinlock consolidation 2005-09-10 10:06:21 -07:00
asm-sh [PATCH] spinlock consolidation 2005-09-10 10:06:21 -07:00
asm-sh64 [PATCH] Clean up struct flock64 definitions 2005-09-07 16:57:38 -07:00
asm-sparc [PATCH] spinlock consolidation 2005-09-10 10:06:21 -07:00
asm-sparc64 [PATCH] spinlock consolidation 2005-09-10 10:06:21 -07:00
asm-um [PATCH] remove asm-*/hdreg.h 2005-09-07 16:57:30 -07:00
asm-v850 [PATCH] Clean up struct flock64 definitions 2005-09-07 16:57:38 -07:00
asm-x86_64 [PATCH] spinlock consolidation 2005-09-10 10:06:21 -07:00
asm-xtensa kbuild: m68k,parisc,ppc,ppc64,s390,xtensa use generic asm-offsets.h support 2005-09-09 20:57:26 +02:00
linux [PATCH] cpuset semaphore depth check deadlock fix 2005-09-10 10:06:21 -07:00
math-emu
media [PATCH] v4l: tveeprom improved to support newer Hauppage cards 2005-09-09 13:57:54 -07:00
mtd
net [AX.25]: Make asc2ax() thread-proof 2005-09-08 13:40:41 -07:00
pcmcia [PATCH] pcmcia: add pcmcia to IRQ information 2005-09-09 13:57:48 -07:00
rdma [PATCH] IB: move include files to include/rdma 2005-08-26 20:37:38 -07:00
rxrpc
scsi Merge by hand (conflicts in sd.c) 2005-09-06 17:52:54 -05:00
sound [PATCH] DocBook: fix kernel-api documentation generation 2005-09-09 14:03:43 -07:00
video [PATCH] framebuffer: new driver for cyberblade/i1 graphics core 2005-09-09 13:58:02 -07:00