NFS: Fix a write request leak in nfs_invalidate_page()
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 28 Aug 2007 14:29:36 +0000 (10:29 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Sat, 1 Sep 2007 14:14:54 +0000 (10:14 -0400)
commit1b3b4a1a2deb7d3e5d66063bd76304d840c966b3
treedfa71fe35420aa18997cabff53afcf3a0db0825a
parent7d1cca72994c0e910ca443076dcfcfd473871dda
NFS: Fix a write request leak in nfs_invalidate_page()

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: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/file.c
fs/nfs/write.c
include/linux/nfs_fs.h