diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-04-02 18:48:28 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2007-05-01 01:17:05 -0400 |
commit | 8b09bee3083897e375bd0bf9d60f48daedfab3e0 (patch) | |
tree | 5122ee611fc46799660db63442107e5677234266 | |
parent | bcb71bba7e64f0442d0ca339d7d3117a7060589f (diff) |
NFS: Cleanup for nfs_readpages()
Do the coalescing of read requests into block sized requests at start of
I/O as we scan through the pages instead of going through a second pass.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/pagelist.c | 4 | ||||
-rw-r--r-- | fs/nfs/read.c | 47 | ||||
-rw-r--r-- | include/linux/nfs_page.h | 2 |
3 files changed, 19 insertions, 34 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 528128545d66..094537ddd344 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -342,8 +342,8 @@ static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc) | |||
342 | * Returns true if the request 'req' was successfully coalesced into the | 342 | * Returns true if the request 'req' was successfully coalesced into the |
343 | * existing list of pages 'desc'. | 343 | * existing list of pages 'desc'. |
344 | */ | 344 | */ |
345 | static int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, | 345 | int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc, |
346 | struct nfs_page *req) | 346 | struct nfs_page *req) |
347 | { | 347 | { |
348 | while (!nfs_pageio_do_add_request(desc, req)) { | 348 | while (!nfs_pageio_do_add_request(desc, req)) { |
349 | nfs_pageio_doio(desc); | 349 | nfs_pageio_doio(desc); |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 0effa74992df..f0016062340d 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -321,28 +321,6 @@ out_bad: | |||
321 | return -ENOMEM; | 321 | return -ENOMEM; |
322 | } | 322 | } |
323 | 323 | ||
324 | static int | ||
325 | nfs_pagein_list(struct inode *inode, struct list_head *head, unsigned int rsize) | ||
326 | { | ||
327 | struct nfs_pageio_descriptor desc; | ||
328 | unsigned int pages = 0; | ||
329 | int error = 0; | ||
330 | |||
331 | if (rsize < PAGE_CACHE_SIZE) | ||
332 | nfs_pageio_init(&desc, inode, nfs_pagein_multi, rsize, 0); | ||
333 | else | ||
334 | nfs_pageio_init(&desc, inode, nfs_pagein_one, rsize, 0); | ||
335 | |||
336 | nfs_pageio_add_list(&desc, head); | ||
337 | nfs_pageio_complete(&desc); | ||
338 | pages += (desc.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | ||
339 | |||
340 | nfs_async_read_error(head); | ||
341 | if (error >= 0) | ||
342 | return pages; | ||
343 | return error; | ||
344 | } | ||
345 | |||
346 | /* | 324 | /* |
347 | * This is the callback from RPC telling us whether a reply was | 325 | * This is the callback from RPC telling us whether a reply was |
348 | * received or some error occurred (timeout or socket shutdown). | 326 | * received or some error occurred (timeout or socket shutdown). |
@@ -532,7 +510,7 @@ out_error: | |||
532 | } | 510 | } |
533 | 511 | ||
534 | struct nfs_readdesc { | 512 | struct nfs_readdesc { |
535 | struct list_head *head; | 513 | struct nfs_pageio_descriptor *pgio; |
536 | struct nfs_open_context *ctx; | 514 | struct nfs_open_context *ctx; |
537 | }; | 515 | }; |
538 | 516 | ||
@@ -556,19 +534,21 @@ readpage_async_filler(void *data, struct page *page) | |||
556 | } | 534 | } |
557 | if (len < PAGE_CACHE_SIZE) | 535 | if (len < PAGE_CACHE_SIZE) |
558 | memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); | 536 | memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); |
559 | nfs_list_add_request(new, desc->head); | 537 | nfs_pageio_add_request(desc->pgio, new); |
560 | return 0; | 538 | return 0; |
561 | } | 539 | } |
562 | 540 | ||
563 | int nfs_readpages(struct file *filp, struct address_space *mapping, | 541 | int nfs_readpages(struct file *filp, struct address_space *mapping, |
564 | struct list_head *pages, unsigned nr_pages) | 542 | struct list_head *pages, unsigned nr_pages) |
565 | { | 543 | { |
566 | LIST_HEAD(head); | 544 | struct nfs_pageio_descriptor pgio; |
567 | struct nfs_readdesc desc = { | 545 | struct nfs_readdesc desc = { |
568 | .head = &head, | 546 | .pgio = &pgio, |
569 | }; | 547 | }; |
570 | struct inode *inode = mapping->host; | 548 | struct inode *inode = mapping->host; |
571 | struct nfs_server *server = NFS_SERVER(inode); | 549 | struct nfs_server *server = NFS_SERVER(inode); |
550 | size_t rsize = server->rsize; | ||
551 | unsigned long npages; | ||
572 | int ret = -ESTALE; | 552 | int ret = -ESTALE; |
573 | 553 | ||
574 | dprintk("NFS: nfs_readpages (%s/%Ld %d)\n", | 554 | dprintk("NFS: nfs_readpages (%s/%Ld %d)\n", |
@@ -587,13 +567,16 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, | |||
587 | } else | 567 | } else |
588 | desc.ctx = get_nfs_open_context((struct nfs_open_context *) | 568 | desc.ctx = get_nfs_open_context((struct nfs_open_context *) |
589 | filp->private_data); | 569 | filp->private_data); |
570 | if (rsize < PAGE_CACHE_SIZE) | ||
571 | nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0); | ||
572 | else | ||
573 | nfs_pageio_init(&pgio, inode, nfs_pagein_one, rsize, 0); | ||
574 | |||
590 | ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc); | 575 | ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc); |
591 | if (!list_empty(&head)) { | 576 | |
592 | int err = nfs_pagein_list(inode, &head, server->rsize); | 577 | nfs_pageio_complete(&pgio); |
593 | if (!ret) | 578 | npages = (pgio.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
594 | nfs_add_stats(inode, NFSIOS_READPAGES, err); | 579 | nfs_add_stats(inode, NFSIOS_READPAGES, npages); |
595 | ret = err; | ||
596 | } | ||
597 | put_nfs_open_context(desc.ctx); | 580 | put_nfs_open_context(desc.ctx); |
598 | out: | 581 | out: |
599 | return ret; | 582 | return ret; |
diff --git a/include/linux/nfs_page.h b/include/linux/nfs_page.h index 91c7b18c47d8..b8b7bca3bac8 100644 --- a/include/linux/nfs_page.h +++ b/include/linux/nfs_page.h | |||
@@ -82,6 +82,8 @@ extern void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | |||
82 | int (*doio)(struct inode *, struct list_head *, size_t, int), | 82 | int (*doio)(struct inode *, struct list_head *, size_t, int), |
83 | size_t bsize, | 83 | size_t bsize, |
84 | int how); | 84 | int how); |
85 | extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *, | ||
86 | struct nfs_page *); | ||
85 | extern void nfs_pageio_add_list(struct nfs_pageio_descriptor *, | 87 | extern void nfs_pageio_add_list(struct nfs_pageio_descriptor *, |
86 | struct list_head *); | 88 | struct list_head *); |
87 | extern void nfs_pageio_complete(struct nfs_pageio_descriptor *desc); | 89 | extern void nfs_pageio_complete(struct nfs_pageio_descriptor *desc); |