• J
    block: fix infinite loop in __getblk_slow · 91f68c89
    Jeff Moyer 提交于
    Commit 080399aa ("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.  This patch has been
    confirmed to fix:
    
        https://bugzilla.redhat.com/show_bug.cgi?id=835019
    
    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.
    Signed-off-by: NJeff Moyer <jmoyer@redhat.com>
    Reported-and-Tested-by: NTorsten Hilbrich <torsten.hilbrich@secunet.com>
    Tested-by: NRichard W.M. Jones <rjones@redhat.com>
    Reviewed-by: NJosh Boyer <jwboyer@redhat.com>
    Cc: Stable <stable@vger.kernel.org>  # 3.0+
    [ Jens is on vacation, taking this directly  - Linus ]
    --
    Stable Notes: this patch requires backport to 3.0, 3.2 and 3.3.
    Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
    91f68c89
buffer.c 85.5 KB