NFS: Don't use page_file_mapping after removing the page
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: 8fc75bed96
("NFS: Fix up return value on fatal errors in nfs_page_async_flush()")
Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
ad6fef7769
commit
d2ceb7e570
|
@ -238,9 +238,9 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
@ -1348,7 +1348,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);
|
||||||
|
@ -1366,7 +1367,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:
|
||||||
|
|
Loading…
Reference in New Issue