Sched fixes, block fixes, fifo fixes, oom fixes, and arm fixes

commit ace1af0eb341b89b2a27e15b01af745a6842445f
Author: faux123 <reioux@gmail.com>
Date:   Tue Jun 26 10:57:43 2012 -0700

    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

commit 320205cd87b5d7721d39628ad043d6b0d3c43ceb
Author: faux123 <reioux@gmail.com>
Date:   Tue Jun 26 10:57:03 2012 -0700

    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

commit 41710ed6e522e0759c2731ad645c6d81a73ceb69
Author: faux123 <reioux@gmail.com>
Date:   Fri Jun 22 15:23:02 2012 -0700

    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

commit 4976087a8d36cdc7587481fcc8f53a2b90eb7374
Author: Peter Zijlstra <a.p.zijlstra@chello.nl>
Date:   Tue Jun 26 10:56:29 2012 -0700

    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.

commit 8c8c04e16d9d3e76736464be5c2c06970885f0c1
Author: faux123 <reioux@gmail.com>
Date:   Sun Jun 3 10:43:13 2012 -0700

    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

commit 9d2fda278bef9067c7fc108e67ffd4b6b26dd8d8
Author: faux123 <reioux@gmail.com>
Date:   Sun Jun 3 10:44:13 2012 -0700

    sched/nohz: Fix rq->cpu_load[] calculations

    While investigating why the load-balancer did funny I found that the
    rq->cpu_load[] tables were completely screwy.. a bit more digging
    revealed that the updates that got through were missing ticks followed
    by a catchup of 2 ticks.

    The catchup assumes the cpu was idle during that time (since only nohz
    can cause missed ticks and the machine is idle etc..) this means that
    esp. the higher indices were significantly lower than they ought to
    be.

    The reason for this is that its not correct to compare against jiffies
    on every jiffy on any other cpu than the cpu that updates jiffies.

    This patch cludges around it by only doing the catch-up stuff from
    nohz_idle_balance() and doing the regular stuff unconditionally from
    the tick.

    Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Cc: pjt@google.com
    Cc: Venkatesh Pallipadi <venki@google.com>
    Link: http://lkml.kernel.org/n/tip-tp4kj18xdd5aj4vvj0qg55s2@git.kernel.org
    Signed-off-by: Ingo Molnar <mingo@kernel.org>
    modified for Linux 3.0 from Linux 3.4+ by faux123

commit 568dd09ac9a70a9ef05dd25befe5cb70f7efa63a
Author: Will Deacon <will.deacon@arm.com>
Date:   Tue May 15 14:15:25 2012 +0100

    ARM: rwlocks: remove unused branch labels from trylock routines

    The ARM arch_{read,write}_trylock implementations include unused
    backwards branch labels, since we don't retry the locking operation
    if the exclusive store fails.

    This patch removes the labels.

    Signed-off-by: Will Deacon <will.deacon@arm.com>