diff options
author | Maxim Patlasov <mpatlasov@parallels.com> | 2012-10-26 11:48:51 -0400 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2013-01-24 10:21:26 -0500 |
commit | f8dbdf81821b5ab4c5e86e7b2bd7edb892c159c2 (patch) | |
tree | c44427d2912a4c4245fe19b59f621a4280a07bf3 /fs | |
parent | 4d53dc99baf139e4fa0d395f7658032cc2eb3297 (diff) |
fuse: rework fuse_readpages()
The patch uses 'nr_pages' argument of fuse_readpages() as heuristics for the
number of page pointers to allocate.
This can be improved further by taking in consideration fc->max_read and gaps
between page indices, but it's not clear whether it's worthy or not.
Signed-off-by: Maxim Patlasov <mpatlasov@parallels.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fuse/file.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 882877125c1d..5fd06bae1790 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -641,6 +641,7 @@ struct fuse_fill_data { | |||
641 | struct fuse_req *req; | 641 | struct fuse_req *req; |
642 | struct file *file; | 642 | struct file *file; |
643 | struct inode *inode; | 643 | struct inode *inode; |
644 | unsigned nr_pages; | ||
644 | }; | 645 | }; |
645 | 646 | ||
646 | static int fuse_readpages_fill(void *_data, struct page *page) | 647 | static int fuse_readpages_fill(void *_data, struct page *page) |
@@ -656,16 +657,25 @@ static int fuse_readpages_fill(void *_data, struct page *page) | |||
656 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || | 657 | (req->num_pages == FUSE_MAX_PAGES_PER_REQ || |
657 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || | 658 | (req->num_pages + 1) * PAGE_CACHE_SIZE > fc->max_read || |
658 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { | 659 | req->pages[req->num_pages - 1]->index + 1 != page->index)) { |
660 | int nr_alloc = min_t(unsigned, data->nr_pages, | ||
661 | FUSE_MAX_PAGES_PER_REQ); | ||
659 | fuse_send_readpages(req, data->file); | 662 | fuse_send_readpages(req, data->file); |
660 | data->req = req = fuse_get_req(fc, FUSE_MAX_PAGES_PER_REQ); | 663 | data->req = req = fuse_get_req(fc, nr_alloc); |
661 | if (IS_ERR(req)) { | 664 | if (IS_ERR(req)) { |
662 | unlock_page(page); | 665 | unlock_page(page); |
663 | return PTR_ERR(req); | 666 | return PTR_ERR(req); |
664 | } | 667 | } |
665 | } | 668 | } |
669 | |||
670 | if (WARN_ON(req->num_pages >= req->max_pages)) { | ||
671 | fuse_put_request(fc, req); | ||
672 | return -EIO; | ||
673 | } | ||
674 | |||
666 | page_cache_get(page); | 675 | page_cache_get(page); |
667 | req->pages[req->num_pages] = page; | 676 | req->pages[req->num_pages] = page; |
668 | req->num_pages++; | 677 | req->num_pages++; |
678 | data->nr_pages--; | ||
669 | return 0; | 679 | return 0; |
670 | } | 680 | } |
671 | 681 | ||
@@ -676,6 +686,7 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
676 | struct fuse_conn *fc = get_fuse_conn(inode); | 686 | struct fuse_conn *fc = get_fuse_conn(inode); |
677 | struct fuse_fill_data data; | 687 | struct fuse_fill_data data; |
678 | int err; | 688 | int err; |
689 | int nr_alloc = min_t(unsigned, nr_pages, FUSE_MAX_PAGES_PER_REQ); | ||
679 | 690 | ||
680 | err = -EIO; | 691 | err = -EIO; |
681 | if (is_bad_inode(inode)) | 692 | if (is_bad_inode(inode)) |
@@ -683,7 +694,8 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
683 | 694 | ||
684 | data.file = file; | 695 | data.file = file; |
685 | data.inode = inode; | 696 | data.inode = inode; |
686 | data.req = fuse_get_req(fc, FUSE_MAX_PAGES_PER_REQ); | 697 | data.req = fuse_get_req(fc, nr_alloc); |
698 | data.nr_pages = nr_pages; | ||
687 | err = PTR_ERR(data.req); | 699 | err = PTR_ERR(data.req); |
688 | if (IS_ERR(data.req)) | 700 | if (IS_ERR(data.req)) |
689 | goto out; | 701 | goto out; |