aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorFred Isaman <iisaman@netapp.com>2012-04-20 14:47:48 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-04-27 14:10:38 -0400
commit061ae2edb7375ab6776468b075da71008a098b55 (patch)
treea34f25d4d85d90a196b058b879eef3ba374f6d16 /fs
parent6c75dc0d498caa402fb17b1bf769835a9db875c8 (diff)
NFS: create completion structure to pass into page_init functions
Factors out the code that will need to change when directio starts using these code paths. This will allow directio to use the generic pagein and flush routines Signed-off-by: Fred Isaman <iisaman@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
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)