summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-02-06 19:07:15 (GMT)
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-02-13 06:40:38 (GMT)
commita301b777714087ea1d63dbec0173a13d416cd7a9 (patch)
treeccf5e747d0411c7af15279c66389ad4e1155ef04
parentb0c4fddca2bc3967381b728732a8850de35e1b20 (diff)
downloadlinux-a301b777714087ea1d63dbec0173a13d416cd7a9.tar.xz
NFS: Don't use ClearPageUptodate() when writeback fails
ClearPageUptodate() will just cause races here. What we really want to do is to invalidate the page cache. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/write.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index dea1737..febdade 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -153,6 +153,13 @@ static void nfs_grow_file(struct page *page, unsigned int offset, unsigned int c
i_size_write(inode, end);
}
+/* A writeback failed: mark the page as bad, and invalidate the page cache */
+static void nfs_set_pageerror(struct page *page)
+{
+ SetPageError(page);
+ nfs_zap_mapping(page->mapping->host, page->mapping);
+}
+
/* We can set the PG_uptodate flag if we see that a write request
* covers the full page.
*/
@@ -714,7 +721,7 @@ int nfs_updatepage(struct file *file, struct page *page,
dprintk("NFS: nfs_updatepage returns %d (isize %Ld)\n",
status, (long long)i_size_read(inode));
if (status < 0)
- ClearPageUptodate(page);
+ nfs_set_pageerror(page);
return status;
}
@@ -976,8 +983,7 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata)
return;
if (task->tk_status < 0) {
- ClearPageUptodate(page);
- SetPageError(page);
+ nfs_set_pageerror(page);
req->wb_context->error = task->tk_status;
dprintk(", error = %d\n", task->tk_status);
} else {
@@ -1034,8 +1040,7 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
(long long)req_offset(req));
if (task->tk_status < 0) {
- ClearPageUptodate(page);
- SetPageError(page);
+ nfs_set_pageerror(page);
req->wb_context->error = task->tk_status;
end_page_writeback(page);
nfs_inode_remove_request(req);