diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/internal.h | 11 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 3 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 39 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 6 | ||||
-rw-r--r-- | fs/nfs/read.c | 36 | ||||
-rw-r--r-- | fs/nfs/write.c | 41 |
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 *, | |||
300 | extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); | 300 | extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); |
301 | #endif | 301 | #endif |
302 | 302 | ||
303 | struct nfs_pgio_completion_ops; | ||
303 | /* read.c */ | 304 | /* read.c */ |
304 | extern void nfs_async_read_error(struct list_head *head); | ||
305 | extern struct nfs_read_header *nfs_readhdr_alloc(void); | 305 | extern struct nfs_read_header *nfs_readhdr_alloc(void); |
306 | extern void nfs_readhdr_free(struct nfs_pgio_header *hdr); | 306 | extern void nfs_readhdr_free(struct nfs_pgio_header *hdr); |
307 | extern void nfs_read_completion(struct nfs_pgio_header *hdr); | ||
308 | extern struct nfs_read_data *nfs_readdata_alloc(struct nfs_pgio_header *hdr, | 307 | extern struct nfs_read_data *nfs_readdata_alloc(struct nfs_pgio_header *hdr, |
309 | unsigned int pagecount); | 308 | unsigned int pagecount); |
310 | extern int nfs_initiate_read(struct rpc_clnt *clnt, | 309 | extern int nfs_initiate_read(struct rpc_clnt *clnt, |
@@ -314,21 +313,21 @@ extern void nfs_read_prepare(struct rpc_task *task, void *calldata); | |||
314 | extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, | 313 | extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, |
315 | struct nfs_pgio_header *hdr); | 314 | struct nfs_pgio_header *hdr); |
316 | extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, | 315 | extern 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); | ||
318 | extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); | 318 | extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); |
319 | extern void nfs_readdata_release(struct nfs_read_data *rdata); | 319 | extern void nfs_readdata_release(struct nfs_read_data *rdata); |
320 | 320 | ||
321 | /* write.c */ | 321 | /* write.c */ |
322 | extern void nfs_async_write_error(struct list_head *head); | ||
323 | extern struct nfs_write_header *nfs_writehdr_alloc(void); | 322 | extern struct nfs_write_header *nfs_writehdr_alloc(void); |
324 | extern void nfs_writehdr_free(struct nfs_pgio_header *hdr); | 323 | extern void nfs_writehdr_free(struct nfs_pgio_header *hdr); |
325 | extern struct nfs_write_data *nfs_writedata_alloc(struct nfs_pgio_header *hdr, | 324 | extern struct nfs_write_data *nfs_writedata_alloc(struct nfs_pgio_header *hdr, |
326 | unsigned int pagecount); | 325 | unsigned int pagecount); |
327 | extern void nfs_write_completion(struct nfs_pgio_header *hdr); | ||
328 | extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, | 326 | extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, |
329 | struct nfs_pgio_header *hdr); | 327 | struct nfs_pgio_header *hdr); |
330 | extern void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, | 328 | extern 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); | ||
332 | extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); | 331 | extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); |
333 | extern void nfs_writedata_release(struct nfs_write_data *wdata); | 332 | extern void nfs_writedata_release(struct nfs_write_data *wdata); |
334 | extern void nfs_commit_free(struct nfs_commit_data *p); | 333 | extern 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 | ||
54 | void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos) | 55 | void 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); | |||
240 | void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | 241 | void 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 * | |||
1113 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write); | 1113 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_init_write); |
1114 | 1114 | ||
1115 | bool | 1115 | bool |
1116 | pnfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, struct inode *inode) | 1116 | pnfs_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 | ||
1127 | bool | 1129 | bool |
1128 | pnfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, struct inode *inode, int ioflags) | 1130 | pnfs_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 | } |
1163 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); | 1168 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); |
1164 | 1169 | ||
1165 | static int pnfs_write_done_resend_to_mds(struct inode *inode, struct list_head *head) | 1170 | static 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 | } |
1315 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages); | 1323 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages); |
1316 | 1324 | ||
1317 | static int pnfs_read_done_resend_to_mds(struct inode *inode, struct list_head *head) | 1325 | static 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 | } |
1467 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages); | 1478 | EXPORT_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); | |||
168 | void get_layout_hdr(struct pnfs_layout_hdr *lo); | 168 | void get_layout_hdr(struct pnfs_layout_hdr *lo); |
169 | void put_lseg(struct pnfs_layout_segment *lseg); | 169 | void put_lseg(struct pnfs_layout_segment *lseg); |
170 | 170 | ||
171 | bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *); | 171 | bool pnfs_pageio_init_read(struct nfs_pageio_descriptor *, struct inode *, |
172 | bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, int); | 172 | const struct nfs_pgio_completion_ops *); |
173 | bool pnfs_pageio_init_write(struct nfs_pageio_descriptor *, struct inode *, | ||
174 | int, const struct nfs_pgio_completion_ops *); | ||
173 | 175 | ||
174 | void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32); | 176 | void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, u32); |
175 | void unset_pnfs_layoutdriver(struct nfs_server *); | 177 | void 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 | ||
32 | static const struct nfs_pageio_ops nfs_pageio_read_ops; | 32 | static const struct nfs_pageio_ops nfs_pageio_read_ops; |
33 | static const struct rpc_call_ops nfs_read_common_ops; | 33 | static const struct rpc_call_ops nfs_read_common_ops; |
34 | static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops; | ||
34 | 35 | ||
35 | static struct kmem_cache *nfs_rdata_cachep; | 36 | static 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 | ||
101 | static | 102 | static |
@@ -108,9 +109,10 @@ int nfs_return_empty_page(struct page *page) | |||
108 | } | 109 | } |
109 | 110 | ||
110 | void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio, | 111 | void 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) | |||
122 | EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds); | 124 | EXPORT_SYMBOL_GPL(nfs_pageio_reset_read_mds); |
123 | 125 | ||
124 | static void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio, | 126 | static 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 | ||
131 | int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode, | 134 | int 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 */ |
173 | void nfs_read_completion(struct nfs_pgio_header *hdr) | 176 | static 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 | ||
303 | void | 306 | static void |
304 | nfs_async_read_error(struct list_head *head) | 307 | nfs_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 | ||
318 | static 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 | */ |
42 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *desc, | 42 | static 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); | ||
44 | static void nfs_redirty_request(struct nfs_page *req); | 45 | static void nfs_redirty_request(struct nfs_page *req); |
45 | static const struct rpc_call_ops nfs_write_common_ops; | 46 | static const struct rpc_call_ops nfs_write_common_ops; |
46 | static const struct rpc_call_ops nfs_commit_ops; | 47 | static const struct rpc_call_ops nfs_commit_ops; |
48 | static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops; | ||
47 | 49 | ||
48 | static struct kmem_cache *nfs_wdata_cachep; | 50 | static struct kmem_cache *nfs_wdata_cachep; |
49 | static mempool_t *nfs_wdata_mempool; | 51 | static 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 | ||
134 | static void nfs_context_set_write_error(struct nfs_open_context *ctx, int error) | 136 | static 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 | ||
561 | void nfs_write_completion(struct nfs_pgio_header *hdr) | 565 | static 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 | ||
1003 | void nfs_async_write_error(struct list_head *head) | 1007 | static 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 | ||
1018 | static 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 | ||
1151 | void nfs_pageio_init_write_mds(struct nfs_pageio_descriptor *pgio, | 1160 | void 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) | |||
1163 | EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds); | 1173 | EXPORT_SYMBOL_GPL(nfs_pageio_reset_write_mds); |
1164 | 1174 | ||
1165 | static void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, | 1175 | static 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 | ||
1172 | void nfs_write_prepare(struct rpc_task *task, void *calldata) | 1183 | void nfs_write_prepare(struct rpc_task *task, void *calldata) |