aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-06 08:57:46 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-01-06 08:57:46 -0500
commite2fecb215b321db0e4a5b2597349a63c07bec42f (patch)
treeeae83638b30a0ae5e742abd8cfb29fd5503e4102
parentfe0fe83585f88346557868a803a479dfaaa0688a (diff)
NFS: Remove pNFS bloat from the generic write path
We have no business doing any this in the standard write release path. Get rid of it, and put it in the pNFS layer. Also, while we're at it, get rid of the completely bogus unlock/relock semantics that were present in nfs_writeback_release_full(). It is not only unnecessary, but actually dangerous to release the write lock just in order to take it again in nfs_page_async_flush(). Better just to open code the pgio operations in a pnfs helper. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/internal.h2
-rw-r--r--fs/nfs/pnfs.c30
-rw-r--r--fs/nfs/write.c27
3 files changed, 32 insertions, 27 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 3f4d95751d5..5ee92538b06 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -307,6 +307,8 @@ extern void nfs_readdata_release(struct nfs_read_data *rdata);
307/* write.c */ 307/* write.c */
308extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, 308extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
309 struct list_head *head); 309 struct list_head *head);
310extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio,
311 struct inode *inode, int ioflags);
310extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); 312extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
311extern void nfs_writedata_release(struct nfs_write_data *wdata); 313extern void nfs_writedata_release(struct nfs_write_data *wdata);
312extern void nfs_commit_free(struct nfs_write_data *p); 314extern void nfs_commit_free(struct nfs_write_data *p);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index f881a638794..17149a49006 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1166,6 +1166,33 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
1166} 1166}
1167EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); 1167EXPORT_SYMBOL_GPL(pnfs_generic_pg_test);
1168 1168
1169static int pnfs_write_done_resend_to_mds(struct inode *inode, struct list_head *head)
1170{
1171 struct nfs_pageio_descriptor pgio;
1172 LIST_HEAD(failed);
1173
1174 /* Resend all requests through the MDS */
1175 nfs_pageio_init_write_mds(&pgio, inode, FLUSH_STABLE);
1176 while (!list_empty(head)) {
1177 struct nfs_page *req = nfs_list_entry(head->next);
1178
1179 nfs_list_remove_request(req);
1180 if (!nfs_pageio_add_request(&pgio, req))
1181 nfs_list_add_request(req, &failed);
1182 }
1183 nfs_pageio_complete(&pgio);
1184
1185 if (!list_empty(&failed)) {
1186 /* For some reason our attempt to resend pages. Mark the
1187 * overall send request as having failed, and let
1188 * nfs_writeback_release_full deal with the error.
1189 */
1190 list_move(&failed, head);
1191 return -EIO;
1192 }
1193 return 0;
1194}
1195
1169/* 1196/*
1170 * Called by non rpc-based layout drivers 1197 * Called by non rpc-based layout drivers
1171 */ 1198 */
@@ -1175,8 +1202,6 @@ void pnfs_ld_write_done(struct nfs_write_data *data)
1175 pnfs_set_layoutcommit(data); 1202 pnfs_set_layoutcommit(data);
1176 data->mds_ops->rpc_call_done(&data->task, data); 1203 data->mds_ops->rpc_call_done(&data->task, data);
1177 } else { 1204 } else {
1178 put_lseg(data->lseg);
1179 data->lseg = NULL;
1180 dprintk("pnfs write error = %d\n", data->pnfs_error); 1205 dprintk("pnfs write error = %d\n", data->pnfs_error);
1181 if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags & 1206 if (NFS_SERVER(data->inode)->pnfs_curr_ld->flags &
1182 PNFS_LAYOUTRET_ON_ERROR) { 1207 PNFS_LAYOUTRET_ON_ERROR) {
@@ -1187,6 +1212,7 @@ void pnfs_ld_write_done(struct nfs_write_data *data)
1187 &NFS_I(data->inode)->flags); 1212 &NFS_I(data->inode)->flags);
1188 pnfs_return_layout(data->inode); 1213 pnfs_return_layout(data->inode);
1189 } 1214 }
1215 data->task.tk_status = pnfs_write_done_resend_to_mds(data->inode, &data->pages);
1190 } 1216 }
1191 data->mds_ops->rpc_release(data); 1217 data->mds_ops->rpc_release(data);
1192} 1218}
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 1dda78db6a7..0c3885255f9 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1052,7 +1052,7 @@ static const struct nfs_pageio_ops nfs_pageio_write_ops = {
1052 .pg_doio = nfs_generic_pg_writepages, 1052 .pg_doio = nfs_generic_pg_writepages,
1053}; 1053};
1054 1054
1055static void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, 1055void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio,
1056 struct inode *inode, int ioflags) 1056 struct inode *inode, int ioflags)
1057{ 1057{
1058 nfs_pageio_init(pgio, inode, &nfs_pageio_write_ops, 1058 nfs_pageio_init(pgio, inode, &nfs_pageio_write_ops,
@@ -1166,13 +1166,7 @@ static void nfs_writeback_done_full(struct rpc_task *task, void *calldata)
1166static void nfs_writeback_release_full(void *calldata) 1166static 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 ret, status = data->task.tk_status; 1169 int 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 }
1176 1170
1177 /* Update attributes as result of writeback. */ 1171 /* Update attributes as result of writeback. */
1178 while (!list_empty(&data->pages)) { 1172 while (!list_empty(&data->pages)) {
@@ -1188,11 +1182,6 @@ static void nfs_writeback_release_full(void *calldata)
1188 req->wb_bytes, 1182 req->wb_bytes,
1189 (long long)req_offset(req)); 1183 (long long)req_offset(req));
1190 1184
1191 if (data->pnfs_error) {
1192 dprintk(", pnfs error = %d\n", data->pnfs_error);
1193 goto next;
1194 }
1195
1196 if (status < 0) { 1185 if (status < 0) {
1197 nfs_set_pageerror(page); 1186 nfs_set_pageerror(page);
1198 nfs_context_set_write_error(req->wb_context, status); 1187 nfs_context_set_write_error(req->wb_context, status);
@@ -1212,19 +1201,7 @@ remove_request:
1212 next: 1201 next:
1213 nfs_clear_page_tag_locked(req); 1202 nfs_clear_page_tag_locked(req);
1214 nfs_end_page_writeback(page); 1203 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 }
1225 } 1204 }
1226 if (data->pnfs_error)
1227 nfs_pageio_complete(&pgio);
1228 nfs_writedata_release(calldata); 1205 nfs_writedata_release(calldata);
1229} 1206}
1230 1207