aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/internal.h11
-rw-r--r--fs/nfs/pagelist.c3
-rw-r--r--fs/nfs/pnfs.c39
-rw-r--r--fs/nfs/pnfs.h6
-rw-r--r--fs/nfs/read.c36
-rw-r--r--fs/nfs/write.c41
6 files changed, 85 insertions, 51 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 16bc9c47c83e..3ef8fcda1a5f 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -300,11 +300,10 @@ extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *,
300extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); 300extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh);
301#endif 301#endif
302 302
303struct nfs_pgio_completion_ops;
303/* read.c */ 304/* read.c */
304extern void nfs_async_read_error(struct list_head *head);
305extern struct nfs_read_header *nfs_readhdr_alloc(void); 305extern struct nfs_read_header *nfs_readhdr_alloc(void);
306extern void nfs_readhdr_free(struct nfs_pgio_header *hdr); 306extern void nfs_readhdr_free(struct nfs_pgio_header *hdr);
307extern void nfs_read_completion(struct nfs_pgio_header *hdr);
308extern struct nfs_read_data *nfs_readdata_alloc(struct nfs_pgio_header *hdr, 307extern struct nfs_read_data *nfs_readdata_alloc(struct nfs_pgio_header *hdr,
309 unsigned int pagecount); 308 unsigned int pagecount);
310extern int nfs_initiate_read(struct rpc_clnt *clnt, 309extern int nfs_initiate_read(struct rpc_clnt *clnt,
@@ -314,21 +313,21 @@ extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
314extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, 313extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
315 struct nfs_pgio_header *hdr); 314 struct nfs_pgio_header *hdr);
316extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, 315extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
317 struct inode *inode); 316 struct inode *inode,
317 const struct nfs_pgio_completion_ops *compl_ops);
318extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); 318extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
319extern void nfs_readdata_release(struct nfs_read_data *rdata); 319extern void nfs_readdata_release(struct nfs_read_data *rdata);
320 320
321/* write.c */ 321/* write.c */
322extern void nfs_async_write_error(struct list_head *head);
323extern struct nfs_write_header *nfs_writehdr_alloc(void); 322extern struct nfs_write_header *nfs_writehdr_alloc(void);
324extern void nfs_writehdr_free(struct nfs_pgio_header *hdr); 323extern void nfs_writehdr_free(struct nfs_pgio_header *hdr);
325extern struct nfs_write_data *nfs_writedata_alloc(struct nfs_pgio_header *hdr, 324extern struct nfs_write_data *nfs_writedata_alloc(struct nfs_pgio_header *hdr,
326 unsigned int pagecount); 325 unsigned int pagecount);
327extern void nfs_write_completion(struct nfs_pgio_header *hdr);
328extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, 326extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc,
329 struct nfs_pgio_header *hdr); 327 struct nfs_pgio_header *hdr);
330extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, 328extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio,
331 struct inode *inode, int ioflags); 329 struct inode *inode, int ioflags,
330 const struct nfs_pgio_completion_ops *compl_ops);
332extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); 331extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio);
333extern void nfs_writedata_release(struct nfs_write_data *wdata); 332extern void nfs_writedata_release(struct nfs_write_data *wdata);
334extern void nfs_commit_free(struct nfs_commit_data *p); 333extern void nfs_commit_free(struct nfs_commit_data *p);
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index cd4c038135a7..4cf2a68493e0 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -49,6 +49,7 @@ void nfs_pgheader_init(struct nfs_pageio_descriptor *desc,
49 hdr->io_start = req_offset(hdr->req); 49 hdr->io_start = req_offset(hdr->req);
50 hdr->good_bytes = desc->pg_count; 50 hdr->good_bytes = desc->pg_count;
51 hdr->release = release; 51 hdr->release = release;
52 hdr->completion_ops = desc->pg_completion_ops;
52} 53}
53 54
54void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos) 55void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos)
@@ -240,6 +241,7 @@ EXPORT_SYMBOL_GPL(nfs_generic_pg_test);
240void nfs_pageio_init(struct nfs_pageio_descriptor *desc, 241void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
241 struct inode *inode, 242 struct inode *inode,
242 const struct nfs_pageio_ops *pg_ops, 243 const struct nfs_pageio_ops *pg_ops,
244 const struct nfs_pgio_completion_ops *compl_ops,
243 size_t bsize, 245 size_t bsize,
244 int io_flags) 246 int io_flags)
245{ 247{
@@ -252,6 +254,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
252 desc->pg_recoalesce = 0; 254 desc->pg_recoalesce = 0;
253 desc->pg_inode = inode; 255 desc->pg_inode = inode;
254 desc->pg_ops = pg_ops; 256 desc->pg_ops = pg_ops;
257 desc->pg_completion_ops = compl_ops;
255 desc->pg_ioflags = io_flags; 258 desc->pg_ioflags = io_flags;
256 desc->pg_error = 0; 259 desc->pg_error = 0;
257 desc->pg_lseg = NULL; 260 desc->pg_lseg = NULL;
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index d515f00614cd..b3a0c01718af 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1113,26 +1113,31 @@ pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *
1113EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write); 1113EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write);
1114 1114
1115bool 1115bool
1116pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode) 1116pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode,
1117 const struct nfs_pgio_completion_ops *compl_ops)
1117{ 1118{
1118 struct nfs_server *server = NFS_SERVER(inode); 1119 struct nfs_server *server = NFS_SERVER(inode);
1119 struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld; 1120 struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;
1120 1121
1121 if (ld == NULL) 1122 if (ld == NULL)
1122 return false; 1123 return false;
1123 nfs_pageio_init(pgio, inode, ld->pg_read_ops, server->rsize, 0); 1124 nfs_pageio_init(pgio, inode, ld->pg_read_ops, compl_ops,
1125 server->rsize, 0);
1124 return true; 1126 return true;
1125} 1127}
1126 1128
1127bool 1129bool
1128pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags) 1130pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode,
1131 int ioflags,
1132 const struct nfs_pgio_completion_ops *compl_ops)
1129{ 1133{
1130 struct nfs_server *server = NFS_SERVER(inode); 1134 struct nfs_server *server = NFS_SERVER(inode);
1131 struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld; 1135 struct pnfs_layoutdriver_type *ld = server->pnfs_curr_ld;
1132 1136
1133 if (ld == NULL) 1137 if (ld == NULL)
1134 return false; 1138 return false;
1135 nfs_pageio_init(pgio, inode, ld->pg_write_ops, server->wsize, ioflags); 1139 nfs_pageio_init(pgio, inode, ld->pg_write_ops, compl_ops,
1140 server->wsize, ioflags);
1136 return true; 1141 return true;
1137} 1142}
1138 1143
@@ -1162,13 +1167,15 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
1162} 1167}
1163EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); 1168EXPORT_SYMBOL_GPL(pnfs_generic_pg_test);
1164 1169
1165static int pnfs_write_done_resend_to_mds(struct inode *inode, struct list_head *head) 1170static int pnfs_write_done_resend_to_mds(struct inode *inode,
1171 struct list_head *head,
1172 const struct nfs_pgio_completion_ops *compl_ops)
1166{ 1173{
1167 struct nfs_pageio_descriptor pgio; 1174 struct nfs_pageio_descriptor pgio;
1168 LIST_HEAD(failed); 1175 LIST_HEAD(failed);
1169 1176
1170 /* Resend all requests through the MDS */ 1177 /* Resend all requests through the MDS */
1171 nfs_pageio_init_write_mds(&pgio, inode, FLUSH_STABLE); 1178 nfs_pageio_init_write_mds(&pgio, inode, FLUSH_STABLE, compl_ops);
1172 while (!list_empty(head)) { 1179 while (!list_empty(head)) {
1173 struct nfs_page *req = nfs_list_entry(head->next); 1180 struct nfs_page *req = nfs_list_entry(head->next);
1174 1181
@@ -1201,7 +1208,8 @@ static void pnfs_ld_handle_write_error(struct nfs_write_data *data)
1201 } 1208 }
1202 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) 1209 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags))
1203 data->task.tk_status = pnfs_write_done_resend_to_mds(hdr->inode, 1210 data->task.tk_status = pnfs_write_done_resend_to_mds(hdr->inode,
1204 &hdr->pages); 1211 &hdr->pages,
1212 hdr->completion_ops);
1205} 1213}
1206 1214
1207/* 1215/*
@@ -1292,7 +1300,7 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
1292 1300
1293 whdr = nfs_writehdr_alloc(); 1301 whdr = nfs_writehdr_alloc();
1294 if (!whdr) { 1302 if (!whdr) {
1295 nfs_async_write_error(&desc->pg_list); 1303 desc->pg_completion_ops->error_cleanup(&hdr->pages);
1296 put_lseg(desc->pg_lseg); 1304 put_lseg(desc->pg_lseg);
1297 desc->pg_lseg = NULL; 1305 desc->pg_lseg = NULL;
1298 return -ENOMEM; 1306 return -ENOMEM;
@@ -1309,18 +1317,20 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
1309 } else 1317 } else
1310 pnfs_do_multiple_writes(desc, &hdr->rpc_list, desc->pg_ioflags); 1318 pnfs_do_multiple_writes(desc, &hdr->rpc_list, desc->pg_ioflags);
1311 if (atomic_dec_and_test(&hdr->refcnt)) 1319 if (atomic_dec_and_test(&hdr->refcnt))
1312 nfs_write_completion(hdr); 1320 hdr->completion_ops->completion(hdr);
1313 return ret; 1321 return ret;
1314} 1322}
1315EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages); 1323EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages);
1316 1324
1317static int pnfs_read_done_resend_to_mds(struct inode *inode, struct list_head *head) 1325static int pnfs_read_done_resend_to_mds(struct inode *inode,
1326 struct list_head *head,
1327 const struct nfs_pgio_completion_ops *compl_ops)
1318{ 1328{
1319 struct nfs_pageio_descriptor pgio; 1329 struct nfs_pageio_descriptor pgio;
1320 LIST_HEAD(failed); 1330 LIST_HEAD(failed);
1321 1331
1322 /* Resend all requests through the MDS */ 1332 /* Resend all requests through the MDS */
1323 nfs_pageio_init_read_mds(&pgio, inode); 1333 nfs_pageio_init_read_mds(&pgio, inode, compl_ops);
1324 while (!list_empty(head)) { 1334 while (!list_empty(head)) {
1325 struct nfs_page *req = nfs_list_entry(head->next); 1335 struct nfs_page *req = nfs_list_entry(head->next);
1326 1336
@@ -1349,7 +1359,8 @@ static void pnfs_ld_handle_read_error(struct nfs_read_data *data)
1349 } 1359 }
1350 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) 1360 if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags))
1351 data->task.tk_status = pnfs_read_done_resend_to_mds(hdr->inode, 1361 data->task.tk_status = pnfs_read_done_resend_to_mds(hdr->inode,
1352 &hdr->pages); 1362 &hdr->pages,
1363 hdr->completion_ops);
1353} 1364}
1354 1365
1355/* 1366/*
@@ -1443,7 +1454,7 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
1443 1454
1444 rhdr = nfs_readhdr_alloc(); 1455 rhdr = nfs_readhdr_alloc();
1445 if (!rhdr) { 1456 if (!rhdr) {
1446 nfs_async_read_error(&desc->pg_list); 1457 desc->pg_completion_ops->error_cleanup(&desc->pg_list);
1447 ret = -ENOMEM; 1458 ret = -ENOMEM;
1448 put_lseg(desc->pg_lseg); 1459 put_lseg(desc->pg_lseg);
1449 desc->pg_lseg = NULL; 1460 desc->pg_lseg = NULL;
@@ -1461,7 +1472,7 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
1461 } else 1472 } else
1462 pnfs_do_multiple_reads(desc, &hdr->rpc_list); 1473 pnfs_do_multiple_reads(desc, &hdr->rpc_list);
1463 if (atomic_dec_and_test(&hdr->refcnt)) 1474 if (atomic_dec_and_test(&hdr->refcnt))
1464 nfs_read_completion(hdr); 1475 hdr->completion_ops->completion(hdr);
1465 return ret; 1476 return ret;
1466} 1477}
1467EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages); 1478EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages);
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 442ebf68eeec..734e4eff7fb0 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -168,8 +168,10 @@ extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp);
168void get_layout_hdr(struct pnfs_layout_hdr *lo); 168void get_layout_hdr(struct pnfs_layout_hdr *lo);
169void put_lseg(struct pnfs_layout_segment *lseg); 169void put_lseg(struct pnfs_layout_segment *lseg);
170 170
171bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *); 171bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *,
172bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, int); 172 const struct nfs_pgio_completion_ops *);
173bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *,
174 int, const struct nfs_pgio_completion_ops *);
173 175
174void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32); 176void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32);
175void unset_pnfs_layoutdriver(struct nfs_server *); 177void unset_pnfs_layoutdriver(struct nfs_server *);
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index c9633b2501bd..5e78af162039 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -31,6 +31,7 @@
31 31
32static const struct nfs_pageio_ops nfs_pageio_read_ops; 32static const struct nfs_pageio_ops nfs_pageio_read_ops;
33static const struct rpc_call_ops nfs_read_common_ops; 33static const struct rpc_call_ops nfs_read_common_ops;
34static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops;
34 35
35static struct kmem_cache *nfs_rdata_cachep; 36static struct kmem_cache *nfs_rdata_cachep;
36 37
@@ -95,7 +96,7 @@ void nfs_readdata_release(struct nfs_read_data *rdata)
95 else 96 else
96 rdata->header = NULL; 97 rdata->header = NULL;
97 if (atomic_dec_and_test(&hdr->refcnt)) 98 if (atomic_dec_and_test(&hdr->refcnt))
98 nfs_read_completion(hdr); 99 hdr->completion_ops->completion(hdr);
99} 100}
100 101
101static 102static
@@ -108,9 +109,10 @@ int nfs_return_empty_page(struct page *page)
108} 109}
109 110
110void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, 111void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
111 struct inode *inode) 112 struct inode *inode,
113 const struct nfs_pgio_completion_ops *compl_ops)
112{ 114{
113 nfs_pageio_init(pgio, inode, &nfs_pageio_read_ops, 115 nfs_pageio_init(pgio, inode, &nfs_pageio_read_ops, compl_ops,
114 NFS_SERVER(inode)->rsize, 0); 116 NFS_SERVER(inode)->rsize, 0);
115} 117}
116 118
@@ -122,10 +124,11 @@ void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio)
122EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds); 124EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds);
123 125
124static void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, 126static void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
125 struct inode *inode) 127 struct inode *inode,
128 const struct nfs_pgio_completion_ops *compl_ops)
126{ 129{
127 if (!pnfs_pageio_init_read(pgio, inode)) 130 if (!pnfs_pageio_init_read(pgio, inode, compl_ops))
128 nfs_pageio_init_read_mds(pgio, inode); 131 nfs_pageio_init_read_mds(pgio, inode, compl_ops);
129} 132}
130 133
131int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, 134int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
@@ -146,7 +149,7 @@ int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
146 if (len < PAGE_CACHE_SIZE) 149 if (len < PAGE_CACHE_SIZE)
147 zero_user_segment(page, len, PAGE_CACHE_SIZE); 150 zero_user_segment(page, len, PAGE_CACHE_SIZE);
148 151
149 nfs_pageio_init_read(&pgio, inode); 152 nfs_pageio_init_read(&pgio, inode, &nfs_async_read_completion_ops);
150 nfs_pageio_add_request(&pgio, new); 153 nfs_pageio_add_request(&pgio, new);
151 nfs_pageio_complete(&pgio); 154 nfs_pageio_complete(&pgio);
152 return 0; 155 return 0;
@@ -170,7 +173,7 @@ static void nfs_readpage_release(struct nfs_page *req)
170} 173}
171 174
172/* Note io was page aligned */ 175/* Note io was page aligned */
173void nfs_read_completion(struct nfs_pgio_header *hdr) 176static void nfs_read_completion(struct nfs_pgio_header *hdr)
174{ 177{
175 unsigned long bytes = 0; 178 unsigned long bytes = 0;
176 179
@@ -300,7 +303,7 @@ nfs_do_multiple_reads(struct list_head *head,
300 return ret; 303 return ret;
301} 304}
302 305
303void 306static void
304nfs_async_read_error(struct list_head *head) 307nfs_async_read_error(struct list_head *head)
305{ 308{
306 struct nfs_page *req; 309 struct nfs_page *req;
@@ -312,6 +315,11 @@ nfs_async_read_error(struct list_head *head)
312 } 315 }
313} 316}
314 317
318static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops = {
319 .error_cleanup = nfs_async_read_error,
320 .completion = nfs_read_completion,
321};
322
315/* 323/*
316 * Generate multiple requests to fill a single page. 324 * Generate multiple requests to fill a single page.
317 * 325 *
@@ -362,7 +370,7 @@ out_bad:
362 list_del(&data->list); 370 list_del(&data->list);
363 nfs_readdata_release(data); 371 nfs_readdata_release(data);
364 } 372 }
365 nfs_async_read_error(&hdr->pages); 373 desc->pg_completion_ops->error_cleanup(&hdr->pages);
366 return -ENOMEM; 374 return -ENOMEM;
367} 375}
368 376
@@ -378,7 +386,7 @@ static int nfs_pagein_one(struct nfs_pageio_descriptor *desc,
378 data = nfs_readdata_alloc(hdr, nfs_page_array_len(desc->pg_base, 386 data = nfs_readdata_alloc(hdr, nfs_page_array_len(desc->pg_base,
379 desc->pg_count)); 387 desc->pg_count));
380 if (!data) { 388 if (!data) {
381 nfs_async_read_error(head); 389 desc->pg_completion_ops->error_cleanup(head);
382 ret = -ENOMEM; 390 ret = -ENOMEM;
383 goto out; 391 goto out;
384 } 392 }
@@ -414,7 +422,7 @@ static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
414 422
415 rhdr = nfs_readhdr_alloc(); 423 rhdr = nfs_readhdr_alloc();
416 if (!rhdr) { 424 if (!rhdr) {
417 nfs_async_read_error(&desc->pg_list); 425 desc->pg_completion_ops->error_cleanup(&desc->pg_list);
418 return -ENOMEM; 426 return -ENOMEM;
419 } 427 }
420 hdr = &rhdr->header; 428 hdr = &rhdr->header;
@@ -427,7 +435,7 @@ static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc)
427 else 435 else
428 set_bit(NFS_IOHDR_REDO, &hdr->flags); 436 set_bit(NFS_IOHDR_REDO, &hdr->flags);
429 if (atomic_dec_and_test(&hdr->refcnt)) 437 if (atomic_dec_and_test(&hdr->refcnt))
430 nfs_read_completion(hdr); 438 hdr->completion_ops->completion(hdr);
431 return ret; 439 return ret;
432} 440}
433 441
@@ -652,7 +660,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
652 if (ret == 0) 660 if (ret == 0)
653 goto read_complete; /* all pages were read */ 661 goto read_complete; /* all pages were read */
654 662
655 nfs_pageio_init_read(&pgio, inode); 663 nfs_pageio_init_read(&pgio, inode, &nfs_async_read_completion_ops);
656 664
657 ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc); 665 ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
658 666
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 076075eb676c..150397279b8d 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -40,10 +40,12 @@
40 * Local function declarations 40 * Local function declarations
41 */ 41 */
42static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc, 42static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc,
43 struct inode *inode, int ioflags); 43 struct inode *inode, int ioflags,
44 const struct nfs_pgio_completion_ops *compl_ops);
44static void nfs_redirty_request(struct nfs_page *req); 45static void nfs_redirty_request(struct nfs_page *req);
45static const struct rpc_call_ops nfs_write_common_ops; 46static const struct rpc_call_ops nfs_write_common_ops;
46static const struct rpc_call_ops nfs_commit_ops; 47static const struct rpc_call_ops nfs_commit_ops;
48static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops;
47 49
48static struct kmem_cache *nfs_wdata_cachep; 50static struct kmem_cache *nfs_wdata_cachep;
49static mempool_t *nfs_wdata_mempool; 51static mempool_t *nfs_wdata_mempool;
@@ -128,7 +130,7 @@ void nfs_writedata_release(struct nfs_write_data *wdata)
128 else 130 else
129 wdata->header = NULL; 131 wdata->header = NULL;
130 if (atomic_dec_and_test(&hdr->refcnt)) 132 if (atomic_dec_and_test(&hdr->refcnt))
131 nfs_write_completion(hdr); 133 hdr->completion_ops->completion(hdr);
132} 134}
133 135
134static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) 136static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error)
@@ -337,7 +339,8 @@ static int nfs_writepage_locked(struct page *page, struct writeback_control *wbc
337 struct nfs_pageio_descriptor pgio; 339 struct nfs_pageio_descriptor pgio;
338 int err; 340 int err;
339 341
340 nfs_pageio_init_write(&pgio, page->mapping->host, wb_priority(wbc)); 342 nfs_pageio_init_write(&pgio, page->mapping->host, wb_priority(wbc),
343 &nfs_async_write_completion_ops);
341 err = nfs_do_writepage(page, wbc, &pgio); 344 err = nfs_do_writepage(page, wbc, &pgio);
342 nfs_pageio_complete(&pgio); 345 nfs_pageio_complete(&pgio);
343 if (err < 0) 346 if (err < 0)
@@ -380,7 +383,8 @@ int nfs_writepages(struct address_space *mapping, struct writeback_control *wbc)
380 383
381 nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES); 384 nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGES);
382 385
383 nfs_pageio_init_write(&pgio, inode, wb_priority(wbc)); 386 nfs_pageio_init_write(&pgio, inode, wb_priority(wbc),
387 &nfs_async_write_completion_ops);
384 err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio); 388 err = write_cache_pages(mapping, wbc, nfs_writepages_callback, &pgio);
385 nfs_pageio_complete(&pgio); 389 nfs_pageio_complete(&pgio);
386 390
@@ -558,7 +562,7 @@ int nfs_write_need_commit(struct nfs_write_data *data)
558 562
559#endif 563#endif
560 564
561void nfs_write_completion(struct nfs_pgio_header *hdr) 565static void nfs_write_completion(struct nfs_pgio_header *hdr)
562{ 566{
563 unsigned long bytes = 0; 567 unsigned long bytes = 0;
564 568
@@ -1000,7 +1004,7 @@ static void nfs_redirty_request(struct nfs_page *req)
1000 nfs_end_page_writeback(page); 1004 nfs_end_page_writeback(page);
1001} 1005}
1002 1006
1003void nfs_async_write_error(struct list_head *head) 1007static void nfs_async_write_error(struct list_head *head)
1004{ 1008{
1005 struct nfs_page *req; 1009 struct nfs_page *req;
1006 1010
@@ -1011,6 +1015,11 @@ void nfs_async_write_error(struct list_head *head)
1011 } 1015 }
1012} 1016}
1013 1017
1018static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops = {
1019 .error_cleanup = nfs_async_write_error,
1020 .completion = nfs_write_completion,
1021};
1022
1014/* 1023/*
1015 * Generate multiple small requests to write out a single 1024 * Generate multiple small requests to write out a single
1016 * contiguous dirty area on one page. 1025 * contiguous dirty area on one page.
@@ -1060,7 +1069,7 @@ out_bad:
1060 list_del(&data->list); 1069 list_del(&data->list);
1061 nfs_writedata_release(data); 1070 nfs_writedata_release(data);
1062 } 1071 }
1063 nfs_async_write_error(&hdr->pages); 1072 desc->pg_completion_ops->error_cleanup(&hdr->pages);
1064 return -ENOMEM; 1073 return -ENOMEM;
1065} 1074}
1066 1075
@@ -1084,7 +1093,7 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc,
1084 data = nfs_writedata_alloc(hdr, nfs_page_array_len(desc->pg_base, 1093 data = nfs_writedata_alloc(hdr, nfs_page_array_len(desc->pg_base,
1085 desc->pg_count)); 1094 desc->pg_count));
1086 if (!data) { 1095 if (!data) {
1087 nfs_async_write_error(head); 1096 desc->pg_completion_ops->error_cleanup(head);
1088 ret = -ENOMEM; 1097 ret = -ENOMEM;
1089 goto out; 1098 goto out;
1090 } 1099 }
@@ -1125,7 +1134,7 @@ static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
1125 1134
1126 whdr = nfs_writehdr_alloc(); 1135 whdr = nfs_writehdr_alloc();
1127 if (!whdr) { 1136 if (!whdr) {
1128 nfs_async_write_error(&desc->pg_list); 1137 desc->pg_completion_ops->error_cleanup(&hdr->pages);
1129 return -ENOMEM; 1138 return -ENOMEM;
1130 } 1139 }
1131 hdr = &whdr->header; 1140 hdr = &whdr->header;
@@ -1139,7 +1148,7 @@ static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
1139 else 1148 else
1140 set_bit(NFS_IOHDR_REDO, &hdr->flags); 1149 set_bit(NFS_IOHDR_REDO, &hdr->flags);
1141 if (atomic_dec_and_test(&hdr->refcnt)) 1150 if (atomic_dec_and_test(&hdr->refcnt))
1142 nfs_write_completion(hdr); 1151 hdr->completion_ops->completion(hdr);
1143 return ret; 1152 return ret;
1144} 1153}
1145 1154
@@ -1149,9 +1158,10 @@ static const struct nfs_pageio_ops nfs_pageio_write_ops = {
1149}; 1158};
1150 1159
1151void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, 1160void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio,
1152 struct inode *inode, int ioflags) 1161 struct inode *inode, int ioflags,
1162 const struct nfs_pgio_completion_ops *compl_ops)
1153{ 1163{
1154 nfs_pageio_init(pgio, inode, &nfs_pageio_write_ops, 1164 nfs_pageio_init(pgio, inode, &nfs_pageio_write_ops, compl_ops,
1155 NFS_SERVER(inode)->wsize, ioflags); 1165 NFS_SERVER(inode)->wsize, ioflags);
1156} 1166}
1157 1167
@@ -1163,10 +1173,11 @@ void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio)
1163EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds); 1173EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds);
1164 1174
1165static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, 1175static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
1166 struct inode *inode, int ioflags) 1176 struct inode *inode, int ioflags,
1177 const struct nfs_pgio_completion_ops *compl_ops)
1167{ 1178{
1168 if (!pnfs_pageio_init_write(pgio, inode, ioflags)) 1179 if (!pnfs_pageio_init_write(pgio, inode, ioflags, compl_ops))
1169 nfs_pageio_init_write_mds(pgio, inode, ioflags); 1180 nfs_pageio_init_write_mds(pgio, inode, ioflags, compl_ops);
1170} 1181}
1171 1182
1172void nfs_write_prepare(struct rpc_task *task, void *calldata) 1183void nfs_write_prepare(struct rpc_task *task, void *calldata)