lift iov_iter into {compat_,}do_readv_writev()
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 21 Mar 2015 00:10:21 +0000 (20:10 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sun, 12 Apr 2015 02:26:45 +0000 (22:26 -0400)
get it closer to matching {compat_,}rw_copy_check_uvector().

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

index 99a6ef9..11980f1 100644 (file)
@@ -695,25 +695,23 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to)
 }
 EXPORT_SYMBOL(iov_shorten);
 
-static ssize_t do_iter_readv_writev(struct file *filp, int rw, const struct iovec *iov,
-               unsigned long nr_segs, size_t len, loff_t *ppos, iter_fn_t fn)
+static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter,
+               loff_t *ppos, iter_fn_t fn)
 {
        struct kiocb kiocb;
-       struct iov_iter iter;
        ssize_t ret;
 
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
 
-       iov_iter_init(&iter, rw, iov, nr_segs, len);
-       ret = fn(&kiocb, &iter);
+       ret = fn(&kiocb, iter);
        BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
 }
 
-static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
-               unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn)
+static ssize_t do_sync_readv_writev(struct file *filp, struct iov_iter *iter,
+               loff_t *ppos, iov_fn_t fn)
 {
        struct kiocb kiocb;
        ssize_t ret;
@@ -721,30 +719,23 @@ static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
        init_sync_kiocb(&kiocb, filp);
        kiocb.ki_pos = *ppos;
 
-       ret = fn(&kiocb, iov, nr_segs, kiocb.ki_pos);
+       ret = fn(&kiocb, iter->iov, iter->nr_segs, kiocb.ki_pos);
        BUG_ON(ret == -EIOCBQUEUED);
        *ppos = kiocb.ki_pos;
        return ret;
 }
 
 /* Do it by hand, with file-ops */
-static ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
-               unsigned long nr_segs, loff_t *ppos, io_fn_t fn)
+static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter,
+               loff_t *ppos, io_fn_t fn)
 {
-       struct iovec *vector = iov;
        ssize_t ret = 0;
 
-       while (nr_segs > 0) {
-               void __user *base;
-               size_t len;
+       while (iov_iter_count(iter)) {
+               struct iovec iovec = iov_iter_iovec(iter);
                ssize_t nr;
 
-               base = vector->iov_base;
-               len = vector->iov_len;
-               vector++;
-               nr_segs--;
-
-               nr = fn(filp, base, len, ppos);
+               nr = fn(filp, iovec.iov_base, iovec.iov_len, ppos);
 
                if (nr < 0) {
                        if (!ret)
@@ -752,8 +743,9 @@ static ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
                        break;
                }
                ret += nr;
-               if (nr != len)
+               if (nr != iovec.iov_len)
                        break;
+               iov_iter_advance(iter, nr);
        }
 
        return ret;
@@ -844,6 +836,7 @@ static ssize_t do_readv_writev(int type, struct file *file,
        size_t tot_len;
        struct iovec iovstack[UIO_FASTIOV];
        struct iovec *iov = iovstack;
+       struct iov_iter iter;
        ssize_t ret;
        io_fn_t fn;
        iov_fn_t fnv;
@@ -853,6 +846,7 @@ static ssize_t do_readv_writev(int type, struct file *file,
                                    ARRAY_SIZE(iovstack), iovstack, &iov);
        if (ret <= 0)
                goto out;
+       iov_iter_init(&iter, type, iov, nr_segs, ret);
 
        tot_len = ret;
        ret = rw_verify_area(type, file, pos, tot_len);
@@ -872,13 +866,11 @@ static ssize_t do_readv_writev(int type, struct file *file,
        }
 
        if (iter_fn)
-               ret = do_iter_readv_writev(file, type, iov, nr_segs, tot_len,
-                                               pos, iter_fn);
+               ret = do_iter_readv_writev(file, &iter, pos, iter_fn);
        else if (fnv)
-               ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
-                                               pos, fnv);
+               ret = do_sync_readv_writev(file, &iter, pos, fnv);
        else
-               ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
+               ret = do_loop_readv_writev(file, &iter, pos, fn);
 
        if (type != READ)
                file_end_write(file);
@@ -1024,6 +1016,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
        compat_ssize_t tot_len;
        struct iovec iovstack[UIO_FASTIOV];
        struct iovec *iov = iovstack;
+       struct iov_iter iter;
        ssize_t ret;
        io_fn_t fn;
        iov_fn_t fnv;
@@ -1033,6 +1026,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
                                               UIO_FASTIOV, iovstack, &iov);
        if (ret <= 0)
                goto out;
+       iov_iter_init(&iter, type, iov, nr_segs, ret);
 
        tot_len = ret;
        ret = rw_verify_area(type, file, pos, tot_len);
@@ -1052,13 +1046,11 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
        }
 
        if (iter_fn)
-               ret = do_iter_readv_writev(file, type, iov, nr_segs, tot_len,
-                                               pos, iter_fn);
+               ret = do_iter_readv_writev(file, &iter, pos, iter_fn);
        else if (fnv)
-               ret = do_sync_readv_writev(file, iov, nr_segs, tot_len,
-                                               pos, fnv);
+               ret = do_sync_readv_writev(file, &iter, pos, fnv);
        else
-               ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn);
+               ret = do_loop_readv_writev(file, &iter, pos, fn);
 
        if (type != READ)
                file_end_write(file);