]> git.baikalelectronics.ru Git - kernel.git/commit
drivers/char/mem.c: avoid OOM lockup during large reads from /dev/zero
authorSalman Qazi <sqazi@google.com>
Thu, 4 Jun 2009 22:20:39 +0000 (15:20 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 4 Jun 2009 22:20:39 +0000 (15:20 -0700)
commitea410d9109f242afb1e1de2d33802c4900bd0b99
treeab1d06260232b343bd1d2d7a5d0563500a1de915
parent0e5264cc9b1d36457030cbe343a829f9f924b8e2
drivers/char/mem.c: avoid OOM lockup during large reads from /dev/zero

While running 20 parallel instances of dd as follows:

  #!/bin/bash
  for i in `seq 1 20`; do
           dd if=/dev/zero of=/export/hda3/dd_$i bs=1073741824 count=1 &
  done
  wait

on a 16G machine, we noticed that rather than just killing the processes,
the entire kernel went down.  Stracing dd reveals that it first does an
mmap2, which makes 1GB worth of zero page mappings.  Then it performs a
read on those pages from /dev/zero, and finally it performs a write.

The machine died during the reads.  Looking at the code, it was noticed
that /dev/zero's read operation had been changed by
f9216d29ec734f1f1a0a008fbbd8cc2cb256211b ("remove ZERO_PAGE") from giving
zero page mappings to actually zeroing the page.

The zeroing of the pages causes physical pages to be allocated to the
process.  But, when the process exhausts all the memory that it can, the
kernel cannot kill it, as it is still in the kernel mode allocating more
memory.  Consequently, the kernel eventually crashes.

To fix this, I propose that when a fatal signal is pending during
/dev/zero read operation, we simply return and let the user process die.

Signed-off-by: Salman Qazi <sqazi@google.com>
Cc: Nick Piggin <nickpiggin@yahoo.com.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
[ Modified error return and comment trivially.  - Linus]
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/char/mem.c