diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-12-10 09:05:55 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-12-10 09:05:55 -0500 |
commit | 190f38e5cedc910940b1da9015f00458c18f97b4 (patch) | |
tree | 3b13c1cd5c536b6187b3196610b97e70a0ba0372 /fs | |
parent | 053e324f67b9921fe7de0c4cbc720d29cb4bf207 (diff) |
NFS: Fix nfs_migrate_page()
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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/write.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index a28123be08a6..6d40a538e3db 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1611,15 +1611,16 @@ int nfs_migrate_page(struct address_space *mapping, struct page *newpage, | |||
1611 | if (ret) | 1611 | if (ret) |
1612 | goto out_unlock; | 1612 | goto out_unlock; |
1613 | page_cache_get(newpage); | 1613 | page_cache_get(newpage); |
1614 | spin_lock(&mapping->host->i_lock); | ||
1614 | req->wb_page = newpage; | 1615 | req->wb_page = newpage; |
1615 | SetPagePrivate(newpage); | 1616 | SetPagePrivate(newpage); |
1616 | set_page_private(newpage, page_private(page)); | 1617 | set_page_private(newpage, (unsigned long)req); |
1617 | ClearPagePrivate(page); | 1618 | ClearPagePrivate(page); |
1618 | set_page_private(page, 0); | 1619 | set_page_private(page, 0); |
1620 | spin_unlock(&mapping->host->i_lock); | ||
1619 | page_cache_release(page); | 1621 | page_cache_release(page); |
1620 | out_unlock: | 1622 | out_unlock: |
1621 | nfs_clear_page_tag_locked(req); | 1623 | nfs_clear_page_tag_locked(req); |
1622 | nfs_release_request(req); | ||
1623 | out: | 1624 | out: |
1624 | return ret; | 1625 | return ret; |
1625 | } | 1626 | } |