diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-02-06 14:07:15 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-02-13 01:40:38 -0500 |
commit | a301b777714087ea1d63dbec0173a13d416cd7a9 (patch) | |
tree | ccf5e747d0411c7af15279c66389ad4e1155ef04 /fs/nfs/write.c | |
parent | b0c4fddca2bc3967381b728732a8850de35e1b20 (diff) |
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>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index dea17375eb30..febdade91670 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 | |||
153 | i_size_write(inode, end); | 153 | i_size_write(inode, end); |
154 | } | 154 | } |
155 | 155 | ||
156 | /* A writeback failed: mark the page as bad, and invalidate the page cache */ | ||
157 | static void nfs_set_pageerror(struct page *page) | ||
158 | { | ||
159 | SetPageError(page); | ||
160 | nfs_zap_mapping(page->mapping->host, page->mapping); | ||
161 | } | ||
162 | |||
156 | /* We can set the PG_uptodate flag if we see that a write request | 163 | /* We can set the PG_uptodate flag if we see that a write request |
157 | * covers the full page. | 164 | * covers the full page. |
158 | */ | 165 | */ |
@@ -714,7 +721,7 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
714 | dprintk("NFS: nfs_updatepage returns %d (isize %Ld)\n", | 721 | dprintk("NFS: nfs_updatepage returns %d (isize %Ld)\n", |
715 | status, (long long)i_size_read(inode)); | 722 | status, (long long)i_size_read(inode)); |
716 | if (status < 0) | 723 | if (status < 0) |
717 | ClearPageUptodate(page); | 724 | nfs_set_pageerror(page); |
718 | return status; | 725 | return status; |
719 | } | 726 | } |
720 | 727 | ||
@@ -976,8 +983,7 @@ static void nfs_writeback_done_partial(struct rpc_task *task, void *calldata) | |||
976 | return; | 983 | return; |
977 | 984 | ||
978 | if (task->tk_status < 0) { | 985 | if (task->tk_status < 0) { |
979 | ClearPageUptodate(page); | 986 | nfs_set_pageerror(page); |
980 | SetPageError(page); | ||
981 | req->wb_context->error = task->tk_status; | 987 | req->wb_context->error = task->tk_status; |
982 | dprintk(", error = %d\n", task->tk_status); | 988 | dprintk(", error = %d\n", task->tk_status); |
983 | } else { | 989 | } else { |
@@ -1034,8 +1040,7 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata) | |||
1034 | (long long)req_offset(req)); | 1040 | (long long)req_offset(req)); |
1035 | 1041 | ||
1036 | if (task->tk_status < 0) { | 1042 | if (task->tk_status < 0) { |
1037 | ClearPageUptodate(page); | 1043 | nfs_set_pageerror(page); |
1038 | SetPageError(page); | ||
1039 | req->wb_context->error = task->tk_status; | 1044 | req->wb_context->error = task->tk_status; |
1040 | end_page_writeback(page); | 1045 | end_page_writeback(page); |
1041 | nfs_inode_remove_request(req); | 1046 | nfs_inode_remove_request(req); |