aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-05-16 07:13:16 -0400
committerSteve French <sfrench@us.ibm.com>2012-05-16 21:13:29 -0400
commit8d5ce4d23c79e0f9861b19fc534f5b2dc636f79c (patch)
tree5f9583d0b3d63e142ec4bbda6058da906a8273f6 /fs/cifs/file.c
parent0471ca3fe481cf5ff0ae24c7003f4d9086a02791 (diff)
cifs: abstract out function to marshal the iovec for readv receives
Cached and uncached reads will need to do different things here to handle the difference when the pages are in pagecache and not. Abstract out the function that marshals the page list into a kvec array. Signed-off-by: Jeff Layton <jlayton@redhat.com>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index d210288e4a47..183381d9c4c1 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2654,6 +2654,73 @@ cifs_readv_complete(struct work_struct *work)
2654 cifs_readdata_free(rdata); 2654 cifs_readdata_free(rdata);
2655} 2655}
2656 2656
2657static int
2658cifs_readpages_marshal_iov(struct cifs_readdata *rdata, unsigned int remaining)
2659{
2660 int len = 0;
2661 struct page *page, *tpage;
2662 u64 eof;
2663 pgoff_t eof_index;
2664
2665 /* determine the eof that the server (probably) has */
2666 eof = CIFS_I(rdata->mapping->host)->server_eof;
2667 eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0;
2668 cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index);
2669
2670 rdata->nr_iov = 1;
2671 list_for_each_entry_safe(page, tpage, &rdata->pages, lru) {
2672 if (remaining >= PAGE_CACHE_SIZE) {
2673 /* enough data to fill the page */
2674 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2675 rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE;
2676 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2677 rdata->nr_iov, page->index,
2678 rdata->iov[rdata->nr_iov].iov_base,
2679 rdata->iov[rdata->nr_iov].iov_len);
2680 ++rdata->nr_iov;
2681 len += PAGE_CACHE_SIZE;
2682 remaining -= PAGE_CACHE_SIZE;
2683 } else if (remaining > 0) {
2684 /* enough for partial page, fill and zero the rest */
2685 rdata->iov[rdata->nr_iov].iov_base = kmap(page);
2686 rdata->iov[rdata->nr_iov].iov_len = remaining;
2687 cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu",
2688 rdata->nr_iov, page->index,
2689 rdata->iov[rdata->nr_iov].iov_base,
2690 rdata->iov[rdata->nr_iov].iov_len);
2691 memset(rdata->iov[rdata->nr_iov].iov_base + remaining,
2692 '\0', PAGE_CACHE_SIZE - remaining);
2693 ++rdata->nr_iov;
2694 len += remaining;
2695 remaining = 0;
2696 } else if (page->index > eof_index) {
2697 /*
2698 * The VFS will not try to do readahead past the
2699 * i_size, but it's possible that we have outstanding
2700 * writes with gaps in the middle and the i_size hasn't
2701 * caught up yet. Populate those with zeroed out pages
2702 * to prevent the VFS from repeatedly attempting to
2703 * fill them until the writes are flushed.
2704 */
2705 zero_user(page, 0, PAGE_CACHE_SIZE);
2706 list_del(&page->lru);
2707 lru_cache_add_file(page);
2708 flush_dcache_page(page);
2709 SetPageUptodate(page);
2710 unlock_page(page);
2711 page_cache_release(page);
2712 } else {
2713 /* no need to hold page hostage */
2714 list_del(&page->lru);
2715 lru_cache_add_file(page);
2716 unlock_page(page);
2717 page_cache_release(page);
2718 }
2719 }
2720
2721 return len;
2722}
2723
2657static int cifs_readpages(struct file *file, struct address_space *mapping, 2724static int cifs_readpages(struct file *file, struct address_space *mapping,
2658 struct list_head *page_list, unsigned num_pages) 2725 struct list_head *page_list, unsigned num_pages)
2659{ 2726{
@@ -2777,6 +2844,7 @@ static int cifs_readpages(struct file *file, struct address_space *mapping,
2777 rdata->offset = offset; 2844 rdata->offset = offset;
2778 rdata->bytes = bytes; 2845 rdata->bytes = bytes;
2779 rdata->pid = pid; 2846 rdata->pid = pid;
2847 rdata->marshal_iov = cifs_readpages_marshal_iov;
2780 list_splice_init(&tmplist, &rdata->pages); 2848 list_splice_init(&tmplist, &rdata->pages);
2781 2849
2782 do { 2850 do {