Commit 7f25bba819a38ab7310024a9350655f374707e20

Authored by Al Viro
1 parent 6130f5315e

cifs_iovec_read: keep iov_iter between the calls of cifs_readdata_to_iov()

... we are doing them on adjacent parts of file, so what happens is that
each subsequent call works to rebuild the iov_iter to exact state it
had been abandoned in by previous one.  Just keep it through the entire
cifs_iovec_read().  And use copy_page_to_iter() instead of doing
kmap/copy_to_user/kunmap manually...

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Showing 1 changed file with 17 additions and 45 deletions Side-by-side Diff

... ... @@ -2727,56 +2727,27 @@
2727 2727 /**
2728 2728 * cifs_readdata_to_iov - copy data from pages in response to an iovec
2729 2729 * @rdata: the readdata response with list of pages holding data
2730   - * @iov: vector in which we should copy the data
2731   - * @nr_segs: number of segments in vector
2732   - * @offset: offset into file of the first iovec
2733   - * @copied: used to return the amount of data copied to the iov
  2730 + * @iter: destination for our data
2734 2731 *
2735 2732 * This function copies data from a list of pages in a readdata response into
2736 2733 * an array of iovecs. It will first calculate where the data should go
2737 2734 * based on the info in the readdata and then copy the data into that spot.
2738 2735 */
2739   -static ssize_t
2740   -cifs_readdata_to_iov(struct cifs_readdata *rdata, const struct iovec *iov,
2741   - unsigned long nr_segs, loff_t offset, ssize_t *copied)
  2736 +static int
  2737 +cifs_readdata_to_iov(struct cifs_readdata *rdata, struct iov_iter *iter)
2742 2738 {
2743   - int rc = 0;
2744   - struct iov_iter ii;
2745   - size_t pos = rdata->offset - offset;
2746   - ssize_t remaining = rdata->bytes;
2747   - unsigned char *pdata;
  2739 + size_t remaining = rdata->bytes;
2748 2740 unsigned int i;
2749 2741  
2750   - /* set up iov_iter and advance to the correct offset */
2751   - iov_iter_init(&ii, iov, nr_segs, iov_length(iov, nr_segs), 0);
2752   - iov_iter_advance(&ii, pos);
2753   -
2754   - *copied = 0;
2755 2742 for (i = 0; i < rdata->nr_pages; i++) {
2756   - ssize_t copy;
2757 2743 struct page *page = rdata->pages[i];
2758   -
2759   - /* copy a whole page or whatever's left */
2760   - copy = min_t(ssize_t, remaining, PAGE_SIZE);
2761   -
2762   - /* ...but limit it to whatever space is left in the iov */
2763   - copy = min_t(ssize_t, copy, iov_iter_count(&ii));
2764   -
2765   - /* go while there's data to be copied and no errors */
2766   - if (copy && !rc) {
2767   - pdata = kmap(page);
2768   - rc = memcpy_toiovecend(ii.iov, pdata, ii.iov_offset,
2769   - (int)copy);
2770   - kunmap(page);
2771   - if (!rc) {
2772   - *copied += copy;
2773   - remaining -= copy;
2774   - iov_iter_advance(&ii, copy);
2775   - }
2776   - }
  2744 + size_t copy = min(remaining, PAGE_SIZE);
  2745 + size_t written = copy_page_to_iter(page, 0, copy, iter);
  2746 + remaining -= written;
  2747 + if (written < copy && iov_iter_count(iter) > 0)
  2748 + break;
2777 2749 }
2778   -
2779   - return rc;
  2750 + return remaining ? -EFAULT : 0;
2780 2751 }
2781 2752  
2782 2753 static void
... ... @@ -2851,6 +2822,7 @@
2851 2822 struct cifsFileInfo *open_file;
2852 2823 struct cifs_readdata *rdata, *tmp;
2853 2824 struct list_head rdata_list;
  2825 + struct iov_iter to;
2854 2826 pid_t pid;
2855 2827  
2856 2828 if (!nr_segs)
... ... @@ -2860,6 +2832,8 @@
2860 2832 if (!len)
2861 2833 return 0;
2862 2834  
  2835 + iov_iter_init(&to, iov, nr_segs, len, 0);
  2836 +
2863 2837 INIT_LIST_HEAD(&rdata_list);
2864 2838 cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
2865 2839 open_file = file->private_data;
2866 2840  
... ... @@ -2917,12 +2891,11 @@
2917 2891 if (!list_empty(&rdata_list))
2918 2892 rc = 0;
2919 2893  
  2894 + len = iov_iter_count(&to);
2920 2895 /* the loop below should proceed in the order of increasing offsets */
2921 2896 list_for_each_entry_safe(rdata, tmp, &rdata_list, list) {
2922 2897 again:
2923 2898 if (!rc) {
2924   - ssize_t copied;
2925   -
2926 2899 /* FIXME: freezable sleep too? */
2927 2900 rc = wait_for_completion_killable(&rdata->done);
2928 2901 if (rc)
2929 2902  
... ... @@ -2935,16 +2908,15 @@
2935 2908 goto again;
2936 2909 }
2937 2910 } else {
2938   - rc = cifs_readdata_to_iov(rdata, iov,
2939   - nr_segs, *poffset,
2940   - &copied);
2941   - total_read += copied;
  2911 + rc = cifs_readdata_to_iov(rdata, &to);
2942 2912 }
2943 2913  
2944 2914 }
2945 2915 list_del_init(&rdata->list);
2946 2916 kref_put(&rdata->refcount, cifs_uncached_readdata_release);
2947 2917 }
  2918 +
  2919 + total_read = len - iov_iter_count(&to);
2948 2920  
2949 2921 cifs_stats_bytes_read(tcon, total_read);
2950 2922 *poffset += total_read;