diff options
author | Peng Tao <bergwolf@gmail.com> | 2011-09-22 21:50:14 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-10-18 12:08:13 -0400 |
commit | 8ce160c5ef06cc89c2b6b26bfa5ef7a5ce2c93e0 (patch) | |
tree | 3f9bc67bba0f7cac91677759ed0eceefbf74984e /fs | |
parent | 1b0ae068779874f54b55aac3a2a992bcf3f2c3c4 (diff) |
pnfs: recoalesce when ld write pagelist fails
For pnfs pagelist write failure, we need to pg_recoalesce and resend IO to
mds.
Signed-off-by: Peng Tao <peng_tao@emc.com>
Signed-off-by: Jim Rees <rees@umich.edu>
Cc: stable@kernel.org [3.0]
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/pnfs.c | 20 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 2 | ||||
-rw-r--r-- | fs/nfs/write.c | 25 |
3 files changed, 32 insertions, 15 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 6b19fffa812a..a205c8e2c731 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -1168,23 +1168,17 @@ EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); | |||
1168 | /* | 1168 | /* |
1169 | * Called by non rpc-based layout drivers | 1169 | * Called by non rpc-based layout drivers |
1170 | */ | 1170 | */ |
1171 | int | 1171 | void pnfs_ld_write_done(struct nfs_write_data *data) |
1172 | pnfs_ld_write_done(struct nfs_write_data *data) | ||
1173 | { | 1172 | { |
1174 | int status; | 1173 | if (likely(!data->pnfs_error)) { |
1175 | |||
1176 | if (!data->pnfs_error) { | ||
1177 | pnfs_set_layoutcommit(data); | 1174 | pnfs_set_layoutcommit(data); |
1178 | data->mds_ops->rpc_call_done(&data->task, data); | 1175 | data->mds_ops->rpc_call_done(&data->task, data); |
1179 | data->mds_ops->rpc_release(data); | 1176 | } else { |
1180 | return 0; | 1177 | put_lseg(data->lseg); |
1178 | data->lseg = NULL; | ||
1179 | dprintk("pnfs write error = %d\n", data->pnfs_error); | ||
1181 | } | 1180 | } |
1182 | 1181 | data->mds_ops->rpc_release(data); | |
1183 | dprintk("%s: pnfs_error=%d, retry via MDS\n", __func__, | ||
1184 | data->pnfs_error); | ||
1185 | status = nfs_initiate_write(data, NFS_CLIENT(data->inode), | ||
1186 | data->mds_ops, NFS_FILE_SYNC); | ||
1187 | return status ? : -EAGAIN; | ||
1188 | } | 1182 | } |
1189 | EXPORT_SYMBOL_GPL(pnfs_ld_write_done); | 1183 | EXPORT_SYMBOL_GPL(pnfs_ld_write_done); |
1190 | 1184 | ||
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 94e760eb543a..71c23d40f735 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -201,7 +201,7 @@ void pnfs_set_layoutcommit(struct nfs_write_data *wdata); | |||
201 | void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data); | 201 | void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data); |
202 | int pnfs_layoutcommit_inode(struct inode *inode, bool sync); | 202 | int pnfs_layoutcommit_inode(struct inode *inode, bool sync); |
203 | int _pnfs_return_layout(struct inode *); | 203 | int _pnfs_return_layout(struct inode *); |
204 | int pnfs_ld_write_done(struct nfs_write_data *); | 204 | void pnfs_ld_write_done(struct nfs_write_data *); |
205 | int pnfs_ld_read_done(struct nfs_read_data *); | 205 | int pnfs_ld_read_done(struct nfs_read_data *); |
206 | struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino, | 206 | struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino, |
207 | struct nfs_open_context *ctx, | 207 | struct nfs_open_context *ctx, |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 72813ede029e..106fd0634ab3 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1166,7 +1166,13 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata) | |||
1166 | static void nfs_writeback_release_full(void *calldata) | 1166 | static void nfs_writeback_release_full(void *calldata) |
1167 | { | 1167 | { |
1168 | struct nfs_write_data *data = calldata; | 1168 | struct nfs_write_data *data = calldata; |
1169 | int status = data->task.tk_status; | 1169 | int ret, status = data->task.tk_status; |
1170 | struct nfs_pageio_descriptor pgio; | ||
1171 | |||
1172 | if (data->pnfs_error) { | ||
1173 | nfs_pageio_init_write_mds(&pgio, data->inode, FLUSH_STABLE); | ||
1174 | pgio.pg_recoalesce = 1; | ||
1175 | } | ||
1170 | 1176 | ||
1171 | /* Update attributes as result of writeback. */ | 1177 | /* Update attributes as result of writeback. */ |
1172 | while (!list_empty(&data->pages)) { | 1178 | while (!list_empty(&data->pages)) { |
@@ -1182,6 +1188,11 @@ static void nfs_writeback_release_full(void *calldata) | |||
1182 | req->wb_bytes, | 1188 | req->wb_bytes, |
1183 | (long long)req_offset(req)); | 1189 | (long long)req_offset(req)); |
1184 | 1190 | ||
1191 | if (data->pnfs_error) { | ||
1192 | dprintk(", pnfs error = %d\n", data->pnfs_error); | ||
1193 | goto next; | ||
1194 | } | ||
1195 | |||
1185 | if (status < 0) { | 1196 | if (status < 0) { |
1186 | nfs_set_pageerror(page); | 1197 | nfs_set_pageerror(page); |
1187 | nfs_context_set_write_error(req->wb_context, status); | 1198 | nfs_context_set_write_error(req->wb_context, status); |
@@ -1201,7 +1212,19 @@ remove_request: | |||
1201 | next: | 1212 | next: |
1202 | nfs_clear_page_tag_locked(req); | 1213 | nfs_clear_page_tag_locked(req); |
1203 | nfs_end_page_writeback(page); | 1214 | nfs_end_page_writeback(page); |
1215 | if (data->pnfs_error) { | ||
1216 | lock_page(page); | ||
1217 | nfs_pageio_cond_complete(&pgio, page->index); | ||
1218 | ret = nfs_page_async_flush(&pgio, page, 0); | ||
1219 | if (ret) { | ||
1220 | nfs_set_pageerror(page); | ||
1221 | dprintk("rewrite to MDS error = %d\n", ret); | ||
1222 | } | ||
1223 | unlock_page(page); | ||
1224 | } | ||
1204 | } | 1225 | } |
1226 | if (data->pnfs_error) | ||
1227 | nfs_pageio_complete(&pgio); | ||
1205 | nfs_writedata_release(calldata); | 1228 | nfs_writedata_release(calldata); |
1206 | } | 1229 | } |
1207 | 1230 | ||