NFS: Fix nfs_migrate_page()
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Thu, 10 Dec 2009 14:05:55 +0000 (09:05 -0500)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Thu, 10 Dec 2009 14:05:55 +0000 (09:05 -0500)
The call to migrate_page() will cause the page->private field to be
cleared.
Also fix up the locking around the page->private transfer, so that we ensure
that calls to nfs_page_find_request() don't end up racing.

Finally, fix up a double free bug: nfs_unlock_request() already calls
nfs_release_request() for us...

Reported-by: Wu Fengguang <fengguang.wu@intel.com>
Tested-by: Andi Kleen <andi@firstfloor.org>
Cc: stable@kernel.org
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/write.c

index a28123be08a629a6df819c177b4830963a66dbf0..6d40a538e3dbdf7ae6e4bd2556a158539ef613fe 100644 (file)
@@ -1611,15 +1611,16 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage,
        if (ret)
                goto out_unlock;
        page_cache_get(newpage);
+       spin_lock(&mapping->host->i_lock);
        req->wb_page = newpage;
        SetPagePrivate(newpage);
-       set_page_private(newpage, page_private(page));
+       set_page_private(newpage, (unsigned long)req);
        ClearPagePrivate(page);
        set_page_private(page, 0);
+       spin_unlock(&mapping->host->i_lock);
        page_cache_release(page);
 out_unlock:
        nfs_clear_page_tag_locked(req);
-       nfs_release_request(req);
 out:
        return ret;
 }