| From 190f38e5cedc910940b1da9015f00458c18f97b4 Mon Sep 17 00:00:00 2001 |
| From: Trond Myklebust <Trond.Myklebust@netapp.com> |
| Date: Thu, 10 Dec 2009 09:05:55 -0500 |
| Subject: NFS: Fix nfs_migrate_page() |
| |
| From: Trond Myklebust <Trond.Myklebust@netapp.com> |
| |
| commit 190f38e5cedc910940b1da9015f00458c18f97b4 upstream. |
| |
| 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> |
| Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| fs/nfs/write.c | 5 +++-- |
| 1 file changed, 3 insertions(+), 2 deletions(-) |
| |
| --- a/fs/nfs/write.c |
| +++ b/fs/nfs/write.c |
| @@ -1612,15 +1612,16 @@ int nfs_migrate_page(struct address_spac |
| 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; |
| } |