• Andrew Morton's avatar
    [PATCH] invalidate_inode_pages fixes · caa2f807
    Andrew Morton authored
    Two fixes here.
    
    First:
    
    Fixes a BUG() which occurs if you try to perform O_DIRECT IO against a
    blockdev which has an fs mounted on it.  (We should be able to do
    that).
    
    What happens is that do_invalidatepage() ends up calling
    discard_buffer() on buffers which it couldn't strip.  That clears
    buffer_mapped() against useful things like the superblock buffer_head.
    The next submit_bh() goes BUG over the write of an unmapped buffer.
    
    So just run try_to_release_page() (aka try_to_free_buffers()) on the
    invalidate path.
    
    
    Second:
    
    The invalidate_inode_pages() functions are best-effort pagecache
    shrinkers.  They are used against pages inside i_size and are not
    supposed to throw away dirty data.
    
    However it is possible for another CPU to run set_page_dirty() against
    one of these pages after invalidate_inode_pages() has decided that it
    is clean.  This could happen if someone was performing O_DIRECT IO
    against a file which was also mapped with MAP_SHARED.
    
    So recheck the dirty state of the page inside the mapping->page_lock
    and back out if the page has just been marked dirty.
    
    This will also prevent the remove_from_page_cache() BUG which will occur
    if someone marks the page dirty between the clear_page_dirty() and
    remove_from_page_cache() calls in truncate_complete_page().
    caa2f807
truncate.c 6.78 KB