aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pagelist.c
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@primarydata.com>2014-08-14 17:39:33 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2014-08-22 18:04:44 -0400
commit78270e8fbc2916bfc8305b8f58f33474cce1ec0e (patch)
treed4bdfbcac7d82bcef4f16f2e7e661320a5ebc6dc /fs/nfs/pagelist.c
parentbba5c1887a925a9945d22217d38d58d8b3ba1043 (diff)
nfs: can_coalesce_requests must enforce contiguity
Commit 6094f83864c1d1296566a282cba05ba613f151ee "nfs: allow coalescing of subpage requests" got rid of the requirement that requests cover whole pages, but it made some incorrect assumptions. It turns out that callers of this interface can map adjacent requests (by file position as seen by req_offset + req->wb_bytes) to different pages, even when they could share a page. An example is the direct I/O interface - iov_iter_get_pages_alloc may return one segment with a partial page filled and the next segment (which is adjacent in the file position) starts with a new page. Reported-by: Toralf Förster <toralf.foerster@gmx.de> 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.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index a1d1de7b97c5..932c6cc27a76 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -823,6 +823,14 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev,
823 return false; 823 return false;
824 if (req_offset(req) != req_offset(prev) + prev->wb_bytes) 824 if (req_offset(req) != req_offset(prev) + prev->wb_bytes)
825 return false; 825 return false;
826 if (req->wb_page == prev->wb_page) {
827 if (req->wb_pgbase != prev->wb_pgbase + prev->wb_bytes)
828 return false;
829 } else {
830 if (req->wb_pgbase != 0 ||
831 prev->wb_pgbase + prev->wb_bytes != PAGE_CACHE_SIZE)
832 return false;
833 }
826 } 834 }
827 size = pgio->pg_ops->pg_test(pgio, prev, req); 835 size = pgio->pg_ops->pg_test(pgio, prev, req);
828 WARN_ON_ONCE(size > req->wb_bytes); 836 WARN_ON_ONCE(size > req->wb_bytes);