• Chris Mason's avatar
    [PATCH] __getblk_slow can loop forever when pages are partially mapped · a61e7286
    Chris Mason authored
    When a block device is accessed via read/write, it is possible for some of
    the buffers on a page to be mapped and others not.  __getblk and friends
    assume this can't happen, and can end up looping forever when pages have
    some unmapped buffers.  Picture:
    
    lseek(/dev/xxx, 2048, SEEK_SET)
    write(/dev/xxx, 2048 bytes)
    
    Assuming the block size is 1k, page 0 has 4 buffers, two are mapped by
    __block_prepare_write and two are not.  Next, another process triggers
    getblk(/dev/xxx, blocknr = 0);
    
    __getblk_slow will loop forever.  __find_get_block fails because the buffer
    isn't mapped.  grow_dev_page does nothing because there are buffers on the
    page with the correct size.  madhav@veritas.com and others at Veritas
    tracked this down.
    
    The fix below has two parts.  First, it changes __find_get_block to avoid
    the buffer_error warnings when it finds unmapped buffers on the page.
    
    Second, it changes grow_dev_page to map the buffers on the page by calling
    init_page_buffers.  init_page_buffers is changed so we don't stomp on
    uptodate bits for the buffers.
    Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
    a61e7286
buffer.c 80.1 KB