diff options
author | Anna Schumaker <Anna.Schumaker@netapp.com> | 2014-05-06 09:12:36 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-05-28 18:41:12 -0400 |
commit | ef2c488c073f4f0b3a200745dd8d608c01d69c39 (patch) | |
tree | 7bb53a2479bb8df2bb66b0943f4814e0abb20f8b /fs/nfs | |
parent | 844c9e691d8723853ca8f2de0207683538645824 (diff) |
NFS: Create a generic_pgio function
These functions are almost identical on both the read and write side.
FLUSH_COND_STABLE will never be set for the read path, so leaving it in
the generic code won't hurt anything.
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/internal.h | 10 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 106 | ||||
-rw-r--r-- | fs/nfs/pnfs.c | 4 | ||||
-rw-r--r-- | fs/nfs/read.c | 81 | ||||
-rw-r--r-- | fs/nfs/write.c | 97 |
5 files changed, 106 insertions, 192 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index a4b9e754756b..365cdb11d0de 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -237,14 +237,10 @@ extern void nfs_pgheader_init(struct nfs_pageio_descriptor *desc, | |||
237 | void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos); | 237 | void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos); |
238 | int nfs_iocounter_wait(struct nfs_io_counter *c); | 238 | int nfs_iocounter_wait(struct nfs_io_counter *c); |
239 | 239 | ||
240 | extern const struct rpc_call_ops nfs_pgio_common_ops; | ||
241 | struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *); | 240 | struct nfs_rw_header *nfs_rw_header_alloc(const struct nfs_rw_ops *); |
242 | void nfs_rw_header_free(struct nfs_pgio_header *); | 241 | void nfs_rw_header_free(struct nfs_pgio_header *); |
243 | struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *, unsigned int); | ||
244 | void nfs_pgio_data_release(struct nfs_pgio_data *); | 242 | void nfs_pgio_data_release(struct nfs_pgio_data *); |
245 | int nfs_pgio_error(struct nfs_pageio_descriptor *, struct nfs_pgio_header *); | 243 | int nfs_generic_pgio(struct nfs_pageio_descriptor *, struct nfs_pgio_header *); |
246 | void nfs_pgio_rpcsetup(struct nfs_pgio_data *, unsigned int, unsigned int, int, | ||
247 | struct nfs_commit_info *); | ||
248 | 244 | ||
249 | static inline void nfs_iocounter_init(struct nfs_io_counter *c) | 245 | static inline void nfs_iocounter_init(struct nfs_io_counter *c) |
250 | { | 246 | { |
@@ -410,8 +406,6 @@ extern int nfs_initiate_read(struct rpc_clnt *clnt, | |||
410 | struct nfs_pgio_data *data, | 406 | struct nfs_pgio_data *data, |
411 | const struct rpc_call_ops *call_ops, int flags); | 407 | const struct rpc_call_ops *call_ops, int flags); |
412 | extern void nfs_read_prepare(struct rpc_task *task, void *calldata); | 408 | extern void nfs_read_prepare(struct rpc_task *task, void *calldata); |
413 | extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, | ||
414 | struct nfs_pgio_header *hdr); | ||
415 | extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); | 409 | extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio); |
416 | 410 | ||
417 | /* super.c */ | 411 | /* super.c */ |
@@ -429,8 +423,6 @@ int nfs_remount(struct super_block *sb, int *flags, char *raw_data); | |||
429 | extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, | 423 | extern void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio, |
430 | struct inode *inode, int ioflags, bool force_mds, | 424 | struct inode *inode, int ioflags, bool force_mds, |
431 | const struct nfs_pgio_completion_ops *compl_ops); | 425 | const struct nfs_pgio_completion_ops *compl_ops); |
432 | extern int nfs_generic_flush(struct nfs_pageio_descriptor *desc, | ||
433 | struct nfs_pgio_header *hdr); | ||
434 | extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); | 426 | extern void nfs_pageio_reset_write_mds(struct nfs_pageio_descriptor *pgio); |
435 | extern void nfs_commit_free(struct nfs_commit_data *p); | 427 | extern void nfs_commit_free(struct nfs_commit_data *p); |
436 | extern int nfs_initiate_write(struct rpc_clnt *clnt, | 428 | extern int nfs_initiate_write(struct rpc_clnt *clnt, |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index b0a98daae14c..d8d25a4deb88 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE | 27 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE |
28 | 28 | ||
29 | static struct kmem_cache *nfs_page_cachep; | 29 | static struct kmem_cache *nfs_page_cachep; |
30 | static const struct rpc_call_ops nfs_pgio_common_ops; | ||
30 | 31 | ||
31 | static bool nfs_pgarray_set(struct nfs_page_array *p, unsigned int pagecount) | 32 | static bool nfs_pgarray_set(struct nfs_page_array *p, unsigned int pagecount) |
32 | { | 33 | { |
@@ -338,8 +339,8 @@ EXPORT_SYMBOL_GPL(nfs_rw_header_free); | |||
338 | * @hdr: The header making a request | 339 | * @hdr: The header making a request |
339 | * @pagecount: Number of pages to create | 340 | * @pagecount: Number of pages to create |
340 | */ | 341 | */ |
341 | struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *hdr, | 342 | static struct nfs_pgio_data *nfs_pgio_data_alloc(struct nfs_pgio_header *hdr, |
342 | unsigned int pagecount) | 343 | unsigned int pagecount) |
343 | { | 344 | { |
344 | struct nfs_pgio_data *data, *prealloc; | 345 | struct nfs_pgio_data *data, *prealloc; |
345 | 346 | ||
@@ -396,7 +397,7 @@ EXPORT_SYMBOL_GPL(nfs_pgio_data_release); | |||
396 | * @how: How to commit data (writes only) | 397 | * @how: How to commit data (writes only) |
397 | * @cinfo: Commit information for the call (writes only) | 398 | * @cinfo: Commit information for the call (writes only) |
398 | */ | 399 | */ |
399 | void nfs_pgio_rpcsetup(struct nfs_pgio_data *data, | 400 | static void nfs_pgio_rpcsetup(struct nfs_pgio_data *data, |
400 | unsigned int count, unsigned int offset, | 401 | unsigned int count, unsigned int offset, |
401 | int how, struct nfs_commit_info *cinfo) | 402 | int how, struct nfs_commit_info *cinfo) |
402 | { | 403 | { |
@@ -451,7 +452,7 @@ static void nfs_pgio_prepare(struct rpc_task *task, void *calldata) | |||
451 | * @desc: IO descriptor | 452 | * @desc: IO descriptor |
452 | * @hdr: pageio header | 453 | * @hdr: pageio header |
453 | */ | 454 | */ |
454 | int nfs_pgio_error(struct nfs_pageio_descriptor *desc, | 455 | static int nfs_pgio_error(struct nfs_pageio_descriptor *desc, |
455 | struct nfs_pgio_header *hdr) | 456 | struct nfs_pgio_header *hdr) |
456 | { | 457 | { |
457 | struct nfs_pgio_data *data; | 458 | struct nfs_pgio_data *data; |
@@ -534,6 +535,101 @@ static void nfs_pgio_result(struct rpc_task *task, void *calldata) | |||
534 | data->header->rw_ops->rw_result(task, data); | 535 | data->header->rw_ops->rw_result(task, data); |
535 | } | 536 | } |
536 | 537 | ||
538 | /* | ||
539 | * Generate multiple small requests to read or write a single | ||
540 | * contiguous dirty on one page. | ||
541 | */ | ||
542 | static int nfs_pgio_multi(struct nfs_pageio_descriptor *desc, | ||
543 | struct nfs_pgio_header *hdr) | ||
544 | { | ||
545 | struct nfs_page *req = hdr->req; | ||
546 | struct page *page = req->wb_page; | ||
547 | struct nfs_pgio_data *data; | ||
548 | size_t wsize = desc->pg_bsize, nbytes; | ||
549 | unsigned int offset; | ||
550 | int requests = 0; | ||
551 | struct nfs_commit_info cinfo; | ||
552 | |||
553 | nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq); | ||
554 | |||
555 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | ||
556 | (desc->pg_moreio || nfs_reqs_to_commit(&cinfo) || | ||
557 | desc->pg_count > wsize)) | ||
558 | desc->pg_ioflags &= ~FLUSH_COND_STABLE; | ||
559 | |||
560 | offset = 0; | ||
561 | nbytes = desc->pg_count; | ||
562 | do { | ||
563 | size_t len = min(nbytes, wsize); | ||
564 | |||
565 | data = nfs_pgio_data_alloc(hdr, 1); | ||
566 | if (!data) | ||
567 | return nfs_pgio_error(desc, hdr); | ||
568 | data->pages.pagevec[0] = page; | ||
569 | nfs_pgio_rpcsetup(data, len, offset, desc->pg_ioflags, &cinfo); | ||
570 | list_add(&data->list, &hdr->rpc_list); | ||
571 | requests++; | ||
572 | nbytes -= len; | ||
573 | offset += len; | ||
574 | } while (nbytes != 0); | ||
575 | |||
576 | nfs_list_remove_request(req); | ||
577 | nfs_list_add_request(req, &hdr->pages); | ||
578 | desc->pg_rpc_callops = &nfs_pgio_common_ops; | ||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | /* | ||
583 | * Create an RPC task for the given read or write request and kick it. | ||
584 | * The page must have been locked by the caller. | ||
585 | * | ||
586 | * It may happen that the page we're passed is not marked dirty. | ||
587 | * This is the case if nfs_updatepage detects a conflicting request | ||
588 | * that has been written but not committed. | ||
589 | */ | ||
590 | static int nfs_pgio_one(struct nfs_pageio_descriptor *desc, | ||
591 | struct nfs_pgio_header *hdr) | ||
592 | { | ||
593 | struct nfs_page *req; | ||
594 | struct page **pages; | ||
595 | struct nfs_pgio_data *data; | ||
596 | struct list_head *head = &desc->pg_list; | ||
597 | struct nfs_commit_info cinfo; | ||
598 | |||
599 | data = nfs_pgio_data_alloc(hdr, nfs_page_array_len(desc->pg_base, | ||
600 | desc->pg_count)); | ||
601 | if (!data) | ||
602 | return nfs_pgio_error(desc, hdr); | ||
603 | |||
604 | nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq); | ||
605 | pages = data->pages.pagevec; | ||
606 | while (!list_empty(head)) { | ||
607 | req = nfs_list_entry(head->next); | ||
608 | nfs_list_remove_request(req); | ||
609 | nfs_list_add_request(req, &hdr->pages); | ||
610 | *pages++ = req->wb_page; | ||
611 | } | ||
612 | |||
613 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | ||
614 | (desc->pg_moreio || nfs_reqs_to_commit(&cinfo))) | ||
615 | desc->pg_ioflags &= ~FLUSH_COND_STABLE; | ||
616 | |||
617 | /* Set up the argument struct */ | ||
618 | nfs_pgio_rpcsetup(data, desc->pg_count, 0, desc->pg_ioflags, &cinfo); | ||
619 | list_add(&data->list, &hdr->rpc_list); | ||
620 | desc->pg_rpc_callops = &nfs_pgio_common_ops; | ||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | int nfs_generic_pgio(struct nfs_pageio_descriptor *desc, | ||
625 | struct nfs_pgio_header *hdr) | ||
626 | { | ||
627 | if (desc->pg_bsize < PAGE_CACHE_SIZE) | ||
628 | return nfs_pgio_multi(desc, hdr); | ||
629 | return nfs_pgio_one(desc, hdr); | ||
630 | } | ||
631 | EXPORT_SYMBOL_GPL(nfs_generic_pgio); | ||
632 | |||
537 | static bool nfs_match_open_context(const struct nfs_open_context *ctx1, | 633 | static bool nfs_match_open_context(const struct nfs_open_context *ctx1, |
538 | const struct nfs_open_context *ctx2) | 634 | const struct nfs_open_context *ctx2) |
539 | { | 635 | { |
@@ -741,7 +837,7 @@ void nfs_destroy_nfspagecache(void) | |||
741 | kmem_cache_destroy(nfs_page_cachep); | 837 | kmem_cache_destroy(nfs_page_cachep); |
742 | } | 838 | } |
743 | 839 | ||
744 | const struct rpc_call_ops nfs_pgio_common_ops = { | 840 | static const struct rpc_call_ops nfs_pgio_common_ops = { |
745 | .rpc_call_prepare = nfs_pgio_prepare, | 841 | .rpc_call_prepare = nfs_pgio_prepare, |
746 | .rpc_call_done = nfs_pgio_result, | 842 | .rpc_call_done = nfs_pgio_result, |
747 | .rpc_release = nfs_pgio_release, | 843 | .rpc_release = nfs_pgio_release, |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 54c84c128b2b..0fe670189fd1 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -1607,7 +1607,7 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | |||
1607 | nfs_pgheader_init(desc, hdr, pnfs_writehdr_free); | 1607 | nfs_pgheader_init(desc, hdr, pnfs_writehdr_free); |
1608 | hdr->lseg = pnfs_get_lseg(desc->pg_lseg); | 1608 | hdr->lseg = pnfs_get_lseg(desc->pg_lseg); |
1609 | atomic_inc(&hdr->refcnt); | 1609 | atomic_inc(&hdr->refcnt); |
1610 | ret = nfs_generic_flush(desc, hdr); | 1610 | ret = nfs_generic_pgio(desc, hdr); |
1611 | if (ret != 0) { | 1611 | if (ret != 0) { |
1612 | pnfs_put_lseg(desc->pg_lseg); | 1612 | pnfs_put_lseg(desc->pg_lseg); |
1613 | desc->pg_lseg = NULL; | 1613 | desc->pg_lseg = NULL; |
@@ -1766,7 +1766,7 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) | |||
1766 | nfs_pgheader_init(desc, hdr, pnfs_readhdr_free); | 1766 | nfs_pgheader_init(desc, hdr, pnfs_readhdr_free); |
1767 | hdr->lseg = pnfs_get_lseg(desc->pg_lseg); | 1767 | hdr->lseg = pnfs_get_lseg(desc->pg_lseg); |
1768 | atomic_inc(&hdr->refcnt); | 1768 | atomic_inc(&hdr->refcnt); |
1769 | ret = nfs_generic_pagein(desc, hdr); | 1769 | ret = nfs_generic_pgio(desc, hdr); |
1770 | if (ret != 0) { | 1770 | if (ret != 0) { |
1771 | pnfs_put_lseg(desc->pg_lseg); | 1771 | pnfs_put_lseg(desc->pg_lseg); |
1772 | desc->pg_lseg = NULL; | 1772 | desc->pg_lseg = NULL; |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 64f8eefec76a..4fcef82d78b4 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -237,85 +237,6 @@ static const struct nfs_pgio_completion_ops nfs_async_read_completion_ops = { | |||
237 | .completion = nfs_read_completion, | 237 | .completion = nfs_read_completion, |
238 | }; | 238 | }; |
239 | 239 | ||
240 | /* | ||
241 | * Generate multiple requests to fill a single page. | ||
242 | * | ||
243 | * We optimize to reduce the number of read operations on the wire. If we | ||
244 | * detect that we're reading a page, or an area of a page, that is past the | ||
245 | * end of file, we do not generate NFS read operations but just clear the | ||
246 | * parts of the page that would have come back zero from the server anyway. | ||
247 | * | ||
248 | * We rely on the cached value of i_size to make this determination; another | ||
249 | * client can fill pages on the server past our cached end-of-file, but we | ||
250 | * won't see the new data until our attribute cache is updated. This is more | ||
251 | * or less conventional NFS client behavior. | ||
252 | */ | ||
253 | static int nfs_pagein_multi(struct nfs_pageio_descriptor *desc, | ||
254 | struct nfs_pgio_header *hdr) | ||
255 | { | ||
256 | struct nfs_page *req = hdr->req; | ||
257 | struct page *page = req->wb_page; | ||
258 | struct nfs_pgio_data *data; | ||
259 | size_t rsize = desc->pg_bsize, nbytes; | ||
260 | unsigned int offset; | ||
261 | |||
262 | offset = 0; | ||
263 | nbytes = desc->pg_count; | ||
264 | do { | ||
265 | size_t len = min(nbytes,rsize); | ||
266 | |||
267 | data = nfs_pgio_data_alloc(hdr, 1); | ||
268 | if (!data) | ||
269 | return nfs_pgio_error(desc, hdr); | ||
270 | data->pages.pagevec[0] = page; | ||
271 | nfs_pgio_rpcsetup(data, len, offset, 0, NULL); | ||
272 | list_add(&data->list, &hdr->rpc_list); | ||
273 | nbytes -= len; | ||
274 | offset += len; | ||
275 | } while (nbytes != 0); | ||
276 | |||
277 | nfs_list_remove_request(req); | ||
278 | nfs_list_add_request(req, &hdr->pages); | ||
279 | desc->pg_rpc_callops = &nfs_pgio_common_ops; | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static int nfs_pagein_one(struct nfs_pageio_descriptor *desc, | ||
284 | struct nfs_pgio_header *hdr) | ||
285 | { | ||
286 | struct nfs_page *req; | ||
287 | struct page **pages; | ||
288 | struct nfs_pgio_data *data; | ||
289 | struct list_head *head = &desc->pg_list; | ||
290 | |||
291 | data = nfs_pgio_data_alloc(hdr, nfs_page_array_len(desc->pg_base, | ||
292 | desc->pg_count)); | ||
293 | if (!data) | ||
294 | return nfs_pgio_error(desc, hdr); | ||
295 | |||
296 | pages = data->pages.pagevec; | ||
297 | while (!list_empty(head)) { | ||
298 | req = nfs_list_entry(head->next); | ||
299 | nfs_list_remove_request(req); | ||
300 | nfs_list_add_request(req, &hdr->pages); | ||
301 | *pages++ = req->wb_page; | ||
302 | } | ||
303 | |||
304 | nfs_pgio_rpcsetup(data, desc->pg_count, 0, 0, NULL); | ||
305 | list_add(&data->list, &hdr->rpc_list); | ||
306 | desc->pg_rpc_callops = &nfs_pgio_common_ops; | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | int nfs_generic_pagein(struct nfs_pageio_descriptor *desc, | ||
311 | struct nfs_pgio_header *hdr) | ||
312 | { | ||
313 | if (desc->pg_bsize < PAGE_CACHE_SIZE) | ||
314 | return nfs_pagein_multi(desc, hdr); | ||
315 | return nfs_pagein_one(desc, hdr); | ||
316 | } | ||
317 | EXPORT_SYMBOL_GPL(nfs_generic_pagein); | ||
318 | |||
319 | static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) | 240 | static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) |
320 | { | 241 | { |
321 | struct nfs_rw_header *rhdr; | 242 | struct nfs_rw_header *rhdr; |
@@ -330,7 +251,7 @@ static int nfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) | |||
330 | hdr = &rhdr->header; | 251 | hdr = &rhdr->header; |
331 | nfs_pgheader_init(desc, hdr, nfs_rw_header_free); | 252 | nfs_pgheader_init(desc, hdr, nfs_rw_header_free); |
332 | atomic_inc(&hdr->refcnt); | 253 | atomic_inc(&hdr->refcnt); |
333 | ret = nfs_generic_pagein(desc, hdr); | 254 | ret = nfs_generic_pgio(desc, hdr); |
334 | if (ret == 0) | 255 | if (ret == 0) |
335 | ret = nfs_do_multiple_reads(&hdr->rpc_list, | 256 | ret = nfs_do_multiple_reads(&hdr->rpc_list, |
336 | desc->pg_rpc_callops); | 257 | desc->pg_rpc_callops); |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 02d088b1d8e4..0e34c7024195 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -1044,101 +1044,6 @@ static const struct nfs_pgio_completion_ops nfs_async_write_completion_ops = { | |||
1044 | .completion = nfs_write_completion, | 1044 | .completion = nfs_write_completion, |
1045 | }; | 1045 | }; |
1046 | 1046 | ||
1047 | /* | ||
1048 | * Generate multiple small requests to write out a single | ||
1049 | * contiguous dirty area on one page. | ||
1050 | */ | ||
1051 | static int nfs_flush_multi(struct nfs_pageio_descriptor *desc, | ||
1052 | struct nfs_pgio_header *hdr) | ||
1053 | { | ||
1054 | struct nfs_page *req = hdr->req; | ||
1055 | struct page *page = req->wb_page; | ||
1056 | struct nfs_pgio_data *data; | ||
1057 | size_t wsize = desc->pg_bsize, nbytes; | ||
1058 | unsigned int offset; | ||
1059 | int requests = 0; | ||
1060 | struct nfs_commit_info cinfo; | ||
1061 | |||
1062 | nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq); | ||
1063 | |||
1064 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | ||
1065 | (desc->pg_moreio || nfs_reqs_to_commit(&cinfo) || | ||
1066 | desc->pg_count > wsize)) | ||
1067 | desc->pg_ioflags &= ~FLUSH_COND_STABLE; | ||
1068 | |||
1069 | |||
1070 | offset = 0; | ||
1071 | nbytes = desc->pg_count; | ||
1072 | do { | ||
1073 | size_t len = min(nbytes, wsize); | ||
1074 | |||
1075 | data = nfs_pgio_data_alloc(hdr, 1); | ||
1076 | if (!data) | ||
1077 | return nfs_pgio_error(desc, hdr); | ||
1078 | data->pages.pagevec[0] = page; | ||
1079 | nfs_pgio_rpcsetup(data, len, offset, desc->pg_ioflags, &cinfo); | ||
1080 | list_add(&data->list, &hdr->rpc_list); | ||
1081 | requests++; | ||
1082 | nbytes -= len; | ||
1083 | offset += len; | ||
1084 | } while (nbytes != 0); | ||
1085 | nfs_list_remove_request(req); | ||
1086 | nfs_list_add_request(req, &hdr->pages); | ||
1087 | desc->pg_rpc_callops = &nfs_pgio_common_ops; | ||
1088 | return 0; | ||
1089 | } | ||
1090 | |||
1091 | /* | ||
1092 | * Create an RPC task for the given write request and kick it. | ||
1093 | * The page must have been locked by the caller. | ||
1094 | * | ||
1095 | * It may happen that the page we're passed is not marked dirty. | ||
1096 | * This is the case if nfs_updatepage detects a conflicting request | ||
1097 | * that has been written but not committed. | ||
1098 | */ | ||
1099 | static int nfs_flush_one(struct nfs_pageio_descriptor *desc, | ||
1100 | struct nfs_pgio_header *hdr) | ||
1101 | { | ||
1102 | struct nfs_page *req; | ||
1103 | struct page **pages; | ||
1104 | struct nfs_pgio_data *data; | ||
1105 | struct list_head *head = &desc->pg_list; | ||
1106 | struct nfs_commit_info cinfo; | ||
1107 | |||
1108 | data = nfs_pgio_data_alloc(hdr, nfs_page_array_len(desc->pg_base, | ||
1109 | desc->pg_count)); | ||
1110 | if (!data) | ||
1111 | return nfs_pgio_error(desc, hdr); | ||
1112 | |||
1113 | nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq); | ||
1114 | pages = data->pages.pagevec; | ||
1115 | while (!list_empty(head)) { | ||
1116 | req = nfs_list_entry(head->next); | ||
1117 | nfs_list_remove_request(req); | ||
1118 | nfs_list_add_request(req, &hdr->pages); | ||
1119 | *pages++ = req->wb_page; | ||
1120 | } | ||
1121 | |||
1122 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | ||
1123 | (desc->pg_moreio || nfs_reqs_to_commit(&cinfo))) | ||
1124 | desc->pg_ioflags &= ~FLUSH_COND_STABLE; | ||
1125 | |||
1126 | /* Set up the argument struct */ | ||
1127 | nfs_pgio_rpcsetup(data, desc->pg_count, 0, desc->pg_ioflags, &cinfo); | ||
1128 | list_add(&data->list, &hdr->rpc_list); | ||
1129 | desc->pg_rpc_callops = &nfs_pgio_common_ops; | ||
1130 | return 0; | ||
1131 | } | ||
1132 | |||
1133 | int nfs_generic_flush(struct nfs_pageio_descriptor *desc, | ||
1134 | struct nfs_pgio_header *hdr) | ||
1135 | { | ||
1136 | if (desc->pg_bsize < PAGE_CACHE_SIZE) | ||
1137 | return nfs_flush_multi(desc, hdr); | ||
1138 | return nfs_flush_one(desc, hdr); | ||
1139 | } | ||
1140 | EXPORT_SYMBOL_GPL(nfs_generic_flush); | ||
1141 | |||
1142 | static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | 1047 | static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) |
1143 | { | 1048 | { |
1144 | struct nfs_rw_header *whdr; | 1049 | struct nfs_rw_header *whdr; |
@@ -1153,7 +1058,7 @@ static int nfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc) | |||
1153 | hdr = &whdr->header; | 1058 | hdr = &whdr->header; |
1154 | nfs_pgheader_init(desc, hdr, nfs_rw_header_free); | 1059 | nfs_pgheader_init(desc, hdr, nfs_rw_header_free); |
1155 | atomic_inc(&hdr->refcnt); | 1060 | atomic_inc(&hdr->refcnt); |
1156 | ret = nfs_generic_flush(desc, hdr); | 1061 | ret = nfs_generic_pgio(desc, hdr); |
1157 | if (ret == 0) | 1062 | if (ret == 0) |
1158 | ret = nfs_do_multiple_writes(&hdr->rpc_list, | 1063 | ret = nfs_do_multiple_writes(&hdr->rpc_list, |
1159 | desc->pg_rpc_callops, | 1064 | desc->pg_rpc_callops, |