block: fix infinite loop in __getblk_slow

Hi,

This commit:

commit 080399a
Author: Jeff Moyer <jmoyer@redhat.com>
Date:   Fri May 11 16:34:10 2012 +0200

    block: don't mark buffers beyond end of disk as mapped

exposed a bug in __getblk_slow that causes mount to hang as it loops
infinitely waiting for a buffer that lies beyond the end of the disk to
become uptodate.  The problem was initially reported by Torsten Hilbrich
here: https://lkml.org/lkml/2012/6/18/54, and also reported
independently here:
http://www.sysresccd.org/forums/viewtopic.php?f=13&t=4511, and then
Richard W.M. Jones and Marcos Mello noted a few separate bugzillas also
associated with the same issue.

The main problem is here, in __getblk_slow:

        for (;;) {
                struct buffer_head * bh;
                int ret;
                bh = __find_get_block(bdev, block, size);
                if (bh)
                        return bh;
                ret = grow_buffers(bdev, block, size);
                if (ret < 0)
                        return NULL;
                if (ret == 0)
                        free_more_memory();
        }
__find_get_block does not find the block, since it will not be marked as
mapped, and so grow_buffers is called to fill in the buffers for the
associated page.  I believe the for (;;) loop is there primarily to
retry in the case of memory pressure keeping grow_buffers from
succeeding.  However, we also continue to loop for other cases, like the
block lying beond the end of the disk.  So, the fix I came up with is to
only loop when grow_buffers fails due to memory allocation issues
(return value of 0).

The attached patch was tested by myself, Torsten, and Rich, and was
found to resolve the problem in call cases.

Comments, as always, are appreciated.

Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
Reported-and-Tested-by: Torsten Hilbrich <torsten.hilbrich@secunet.com>
Tested-by: Richard W.M. Jones <rjones@redhat.com>
Cc: Stable <stable@vger.kernel.org>
backported from Linux 3.5+ to Linux 3.0 by faux123
fifo: Do not restart open() if it already found a partner

If a parent and child process open the two ends of a fifo, and the
child immediately exits, the parent may receive a SIGCHLD before its
open() returns.  In that case, we need to make sure that open() will
return successfully after the SIGCHLD handler returns, instead of
throwing EINTR or being restarted.  Otherwise, the restarted open()
would incorrectly wait for a second partner on the other end.

The following test demonstrates the EINTR that was wrongly thrown from
the parent.s open().  Change .sa_flags = 0 to .sa_flags = SA_RESTART
to see a deadlock instead, in which the restarted open() waits for a
second reader that will never come.

  #include <sys/stat.h>
  #include <sys/types.h>
  #include <sys/wait.h>
  #include <fcntl.h>
  #include <signal.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <unistd.h>

  #define CHECK(x) do {if ((x) == -1) {perror(#x); abort();}} while(0)
  void handler(int signum) {}
  int main()
  {
      struct sigaction act = {.sa_handler = handler, .sa_flags = 0};
      CHECK(sigaction(SIGCHLD, &act, NULL));
      CHECK(mknod("fifo", S_IFIFO | S_IRWXU, 0));
      for (;;) {
          int fd;
          pid_t pid;
          putc('.', stderr);
          CHECK(pid = fork());
          if (pid == 0) {
              CHECK(fd = open("fifo", O_RDONLY));
              _exit(0);
          }
          CHECK(fd = open("fifo", O_WRONLY));
          CHECK(close(fd));
          CHECK(waitpid(pid, NULL, 0));
      }
  }
This is what I suspect was causing the Git test suite to fail in
t9010-svn-fe.sh:
http://bugs.debian.org/678852

Signed-off-by: Anders Kaseorg <andersk@mit.edu>
backported to Linux 3.0 from Linux 3.5+ by faux123
mm, oom: fix potential killing of thread that is disabled from oom killing

/proc/sys/vm/oom_kill_allocating_task will immediately kill current when
the oom killer is called to avoid a potentially expensive tasklist scan
for large systems.

Currently, however, it is not checking current's oom_score_adj value
which may be OOM_SCORE_ADJ_MIN, meaning that it has been disabled from
oom killing.

This patch avoids killing current in such a condition and simply falls
back to the tasklist scan since memory still needs to be freed.

Signed-off-by: David Rientjes <rientjes@google.com>
backported to Linux 3.0.x from Linux 3.5+ by faux123
sched/fair: Improve the ->group_imb logic

Group imbalance is meant to deal with situations where affinity masks
and sched domains don't align well, such as 3 cpus from one group and
6 from another. In this case the domain based balancer will want to
put an equal amount of tasks on each side even though they don't have
equal cpus.

Currently group_imb is set whenever two cpus of a group have a weight
difference of at least one avg task and the heaviest cpu has at least
two tasks. A group with imbalance set will always be picked as busiest
and a balance pass will be forced.
The problem is that even if there are no affinity masks this stuff can
trigger and cause weird balancing decisions, eg. the observed
behaviour was that of 6 cpus, 5 had 2 and 1 had 3 tasks, due to the
difference of 1 avg load (they all had the same weight) and nr_running
being >1 the group_imbalance logic triggered and did the weird thing
of pulling more load instead of trying to move the 1 excess task to
the other domain of 6 cpus that had 5 cpu with 2 tasks and 1 cpu with
1 task.
Curb the group_imbalance stuff by making the nr_running condition
weaker by also tracking the min_nr_running and using the difference in
nr_running over the set instead of the absolute max nr_running.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/n/tip-9s7dedozxo8kjsb9kqlrukkf@git.kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
modified for Linux 3.0 from Linux 3.4+ by faux123
sched: clock wrap bug in 2.6.35-stable kills scheduling

On Mon, 2012-06-25 at 11:45 +0200, Peter Zijlstra wrote:
> On Sun, 2012-06-24 at 19:32 +0200, Thomas Lange wrote:
> > Bug was introduced in 2.6.35.12 and is still present in linux-2.6.35.y HEAD.
>
> Ok, so nobody cares about that.. what does something recent like 3.5-rc4
> do?
>
> If that's fixed, find the patch that fixes it. If not, we'll have a
> look.

If anything, I think something like the below ought to cure things.