Commit 6c023d86 authored by Benjamin Coddington's avatar Benjamin Coddington Committed by Greg Kroah-Hartman

NFS: Don't use page_file_mapping after removing the page

[ Upstream commit d2ceb7e5 ]

If nfs_page_async_flush() removes the page from the mapping, then we can't
use page_file_mapping() on it as nfs_updatepate() is wont to do when
receiving an error.  Instead, push the mapping to the stack before the page
is possibly truncated.

Fixes: 8fc75bed ("NFS: Fix up return value on fatal errors in nfs_page_async_flush()")
Signed-off-by: default avatarBenjamin Coddington <bcodding@redhat.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent d84bc704
...@@ -238,9 +238,9 @@ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int c ...@@ -238,9 +238,9 @@ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int c
} }
/* A writeback failed: mark the page as bad, and invalidate the page cache */ /* A writeback failed: mark the page as bad, and invalidate the page cache */
static void nfs_set_pageerror(struct page *page) static void nfs_set_pageerror(struct address_space *mapping)
{ {
nfs_zap_mapping(page_file_mapping(page)->host, page_file_mapping(page)); nfs_zap_mapping(mapping->host, mapping);
} }
/* /*
...@@ -994,7 +994,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr) ...@@ -994,7 +994,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr)
nfs_list_remove_request(req); nfs_list_remove_request(req);
if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) && if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) &&
(hdr->good_bytes < bytes)) { (hdr->good_bytes < bytes)) {
nfs_set_pageerror(req->wb_page); nfs_set_pageerror(page_file_mapping(req->wb_page));
nfs_context_set_write_error(req->wb_context, hdr->error); nfs_context_set_write_error(req->wb_context, hdr->error);
goto remove_req; goto remove_req;
} }
...@@ -1330,7 +1330,8 @@ int nfs_updatepage(struct file *file, struct page *page, ...@@ -1330,7 +1330,8 @@ int nfs_updatepage(struct file *file, struct page *page,
unsigned int offset, unsigned int count) unsigned int offset, unsigned int count)
{ {
struct nfs_open_context *ctx = nfs_file_open_context(file); struct nfs_open_context *ctx = nfs_file_open_context(file);
struct inode *inode = page_file_mapping(page)->host; struct address_space *mapping = page_file_mapping(page);
struct inode *inode = mapping->host;
int status = 0; int status = 0;
nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE); nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE);
...@@ -1348,7 +1349,7 @@ int nfs_updatepage(struct file *file, struct page *page, ...@@ -1348,7 +1349,7 @@ int nfs_updatepage(struct file *file, struct page *page,
status = nfs_writepage_setup(ctx, page, offset, count); status = nfs_writepage_setup(ctx, page, offset, count);
if (status < 0) if (status < 0)
nfs_set_pageerror(page); nfs_set_pageerror(mapping);
else else
__set_page_dirty_nobuffers(page); __set_page_dirty_nobuffers(page);
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment