aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pagelist.c
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@primarydata.com>2014-05-15 11:56:52 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-05-29 11:11:48 -0400
commitf0cb9ab8d5589fc553761068200e5a8342f61de0 (patch)
treeae7f0bc99fa85e90333c2400d050620167dd1b8f /fs/nfs/pagelist.c
parent0f9c429eca07aca2764ccd751e2b48ba5397b936 (diff)
nfs: use > 1 request to handle bsize < PAGE_SIZE
Use the newly added support for multiple requests per page for rsize/wsize < PAGE_SIZE, instead of having multiple read / write data structures per pageio header. This allows us to get rid of nfs_pgio_multi. Signed-off-by: Weston Andros Adamson <dros@primarydata.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/pagelist.c')
-rw-r--r--fs/nfs/pagelist.c80
1 files changed, 11 insertions, 69 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 838f7c9664f5..ec4311df05d9 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -443,21 +443,13 @@ nfs_wait_on_request(struct nfs_page *req)
443size_t nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, 443size_t nfs_generic_pg_test(struct nfs_pageio_descriptor *desc,
444 struct nfs_page *prev, struct nfs_page *req) 444 struct nfs_page *prev, struct nfs_page *req)
445{ 445{
446 if (!prev) 446 if (desc->pg_count > desc->pg_bsize) {
447 return req->wb_bytes; 447 /* should never happen */
448 /* 448 WARN_ON_ONCE(1);
449 * FIXME: ideally we should be able to coalesce all requests
450 * that are not block boundary aligned, but currently this
451 * is problematic for the case of bsize < PAGE_CACHE_SIZE,
452 * since nfs_flush_multi and nfs_pagein_multi assume you
453 * can have only one struct nfs_page.
454 */
455 if (desc->pg_bsize < PAGE_SIZE)
456 return 0; 449 return 0;
450 }
457 451
458 if (desc->pg_count + req->wb_bytes <= desc->pg_bsize) 452 return min(desc->pg_bsize - desc->pg_count, (size_t)req->wb_bytes);
459 return req->wb_bytes;
460 return 0;
461} 453}
462EXPORT_SYMBOL_GPL(nfs_generic_pg_test); 454EXPORT_SYMBOL_GPL(nfs_generic_pg_test);
463 455
@@ -766,50 +758,6 @@ static void nfs_pgio_result(struct rpc_task *task, void *calldata)
766} 758}
767 759
768/* 760/*
769 * Generate multiple small requests to read or write a single
770 * contiguous dirty on one page.
771 */
772static int nfs_pgio_multi(struct nfs_pageio_descriptor *desc,
773 struct nfs_pgio_header *hdr)
774{
775 struct nfs_page *req = hdr->req;
776 struct page *page = req->wb_page;
777 struct nfs_pgio_data *data;
778 size_t wsize = desc->pg_bsize, nbytes;
779 unsigned int offset;
780 int requests = 0;
781 struct nfs_commit_info cinfo;
782
783 nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq);
784
785 if ((desc->pg_ioflags & FLUSH_COND_STABLE) &&
786 (desc->pg_moreio || nfs_reqs_to_commit(&cinfo) ||
787 desc->pg_count > wsize))
788 desc->pg_ioflags &= ~FLUSH_COND_STABLE;
789
790 offset = 0;
791 nbytes = desc->pg_count;
792 do {
793 size_t len = min(nbytes, wsize);
794
795 data = nfs_pgio_data_alloc(hdr, 1);
796 if (!data)
797 return nfs_pgio_error(desc, hdr);
798 data->pages.pagevec[0] = page;
799 nfs_pgio_rpcsetup(data, len, offset, desc->pg_ioflags, &cinfo);
800 list_add(&data->list, &hdr->rpc_list);
801 requests++;
802 nbytes -= len;
803 offset += len;
804 } while (nbytes != 0);
805
806 nfs_list_remove_request(req);
807 nfs_list_add_request(req, &hdr->pages);
808 desc->pg_rpc_callops = &nfs_pgio_common_ops;
809 return 0;
810}
811
812/*
813 * Create an RPC task for the given read or write request and kick it. 761 * Create an RPC task for the given read or write request and kick it.
814 * The page must have been locked by the caller. 762 * The page must have been locked by the caller.
815 * 763 *
@@ -817,8 +765,8 @@ static int nfs_pgio_multi(struct nfs_pageio_descriptor *desc,
817 * This is the case if nfs_updatepage detects a conflicting request 765 * This is the case if nfs_updatepage detects a conflicting request
818 * that has been written but not committed. 766 * that has been written but not committed.
819 */ 767 */
820static int nfs_pgio_one(struct nfs_pageio_descriptor *desc, 768int nfs_generic_pgio(struct nfs_pageio_descriptor *desc,
821 struct nfs_pgio_header *hdr) 769 struct nfs_pgio_header *hdr)
822{ 770{
823 struct nfs_page *req; 771 struct nfs_page *req;
824 struct page **pages; 772 struct page **pages;
@@ -850,6 +798,7 @@ static int nfs_pgio_one(struct nfs_pageio_descriptor *desc,
850 desc->pg_rpc_callops = &nfs_pgio_common_ops; 798 desc->pg_rpc_callops = &nfs_pgio_common_ops;
851 return 0; 799 return 0;
852} 800}
801EXPORT_SYMBOL_GPL(nfs_generic_pgio);
853 802
854static int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *desc) 803static int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *desc)
855{ 804{
@@ -875,15 +824,6 @@ static int nfs_generic_pg_pgios(struct nfs_pageio_descriptor *desc)
875 return ret; 824 return ret;
876} 825}
877 826
878int nfs_generic_pgio(struct nfs_pageio_descriptor *desc,
879 struct nfs_pgio_header *hdr)
880{
881 if (desc->pg_bsize < PAGE_CACHE_SIZE)
882 return nfs_pgio_multi(desc, hdr);
883 return nfs_pgio_one(desc, hdr);
884}
885EXPORT_SYMBOL_GPL(nfs_generic_pgio);
886
887static bool nfs_match_open_context(const struct nfs_open_context *ctx1, 827static bool nfs_match_open_context(const struct nfs_open_context *ctx1,
888 const struct nfs_open_context *ctx2) 828 const struct nfs_open_context *ctx2)
889{ 829{
@@ -925,7 +865,9 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev,
925 return false; 865 return false;
926 } 866 }
927 size = pgio->pg_ops->pg_test(pgio, prev, req); 867 size = pgio->pg_ops->pg_test(pgio, prev, req);
928 WARN_ON_ONCE(size && size != req->wb_bytes); 868 WARN_ON_ONCE(size > req->wb_bytes);
869 if (size && size < req->wb_bytes)
870 req->wb_bytes = size;
929 return size > 0; 871 return size > 0;
930} 872}
931 873