• Trond Myklebust's avatar
    NFS: Fix a write request leak in nfs_invalidate_page() · 1b3b4a1a
    Trond Myklebust authored
    Ryusuke Konishi says:
    
    The recent truncate_complete_page() clears the dirty flag from a page
    before calling a_ops->invalidatepage(),
    ^^^^^^
    static void
    truncate_complete_page(struct address_space *mapping, struct page *page)
    {
            ...
            cancel_dirty_page(page, PAGE_CACHE_SIZE);  <--- Inserted here at
    kernel 2.6.20
    
            if (PagePrivate(page))
                    do_invalidatepage(page, 0);   ---> will call
    a_ops->invalidatepage()
            ...
    }
    
    and this is disturbing nfs_wb_page_priority() from calling 
    nfs_writepage_locked() that is expected to handle the pending
    request (=nfs_page) associated with the page.
    
    int nfs_wb_page_priority(struct inode *inode, struct page *page, int how)
    {
            ...
            if (clear_page_dirty_for_io(page)) {
                    ret = nfs_writepage_locked(page, &wbc);
                    if (ret < 0)
                            goto out;
            }
            ...
    }
    
    Since truncate_complete_page() will get rid of the page after
    a_ops->invalidatepage() returns, the request (=nfs_page) associated
    with the page becomes a garbage in nfs_inode->nfs_page_tree.
    ------------------------
    
    Fix this by ensuring that nfs_wb_page_priority() recognises that it may
    also need to clear out non-dirty pages that have an nfs_page associated
    with them.
    Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
    1b3b4a1a
file.c 15.3 KB