Commit ac15ac06 authored by Al Viro's avatar Al Viro

lift iov_iter into {compat_,}do_readv_writev()

get it closer to matching {compat_,}rw_copy_check_uvector().
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent c0fec3a9
...@@ -695,25 +695,23 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to) ...@@ -695,25 +695,23 @@ unsigned long iov_shorten(struct iovec *iov, unsigned long nr_segs, size_t to)
} }
EXPORT_SYMBOL(iov_shorten); EXPORT_SYMBOL(iov_shorten);
static ssize_t do_iter_readv_writev(struct file *filp, int rw, const struct iovec *iov, static ssize_t do_iter_readv_writev(struct file *filp, struct iov_iter *iter,
unsigned long nr_segs, size_t len, loff_t *ppos, iter_fn_t fn) loff_t *ppos, iter_fn_t fn)
{ {
struct kiocb kiocb; struct kiocb kiocb;
struct iov_iter iter;
ssize_t ret; ssize_t ret;
init_sync_kiocb(&kiocb, filp); init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos; 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); BUG_ON(ret == -EIOCBQUEUED);
*ppos = kiocb.ki_pos; *ppos = kiocb.ki_pos;
return ret; return ret;
} }
static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov, static ssize_t do_sync_readv_writev(struct file *filp, struct iov_iter *iter,
unsigned long nr_segs, size_t len, loff_t *ppos, iov_fn_t fn) loff_t *ppos, iov_fn_t fn)
{ {
struct kiocb kiocb; struct kiocb kiocb;
ssize_t ret; ssize_t ret;
...@@ -721,30 +719,23 @@ static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov, ...@@ -721,30 +719,23 @@ static ssize_t do_sync_readv_writev(struct file *filp, const struct iovec *iov,
init_sync_kiocb(&kiocb, filp); init_sync_kiocb(&kiocb, filp);
kiocb.ki_pos = *ppos; 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); BUG_ON(ret == -EIOCBQUEUED);
*ppos = kiocb.ki_pos; *ppos = kiocb.ki_pos;
return ret; return ret;
} }
/* Do it by hand, with file-ops */ /* Do it by hand, with file-ops */
static ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov, static ssize_t do_loop_readv_writev(struct file *filp, struct iov_iter *iter,
unsigned long nr_segs, loff_t *ppos, io_fn_t fn) loff_t *ppos, io_fn_t fn)
{ {
struct iovec *vector = iov;
ssize_t ret = 0; ssize_t ret = 0;
while (nr_segs > 0) { while (iov_iter_count(iter)) {
void __user *base; struct iovec iovec = iov_iter_iovec(iter);
size_t len;
ssize_t nr; ssize_t nr;
base = vector->iov_base; nr = fn(filp, iovec.iov_base, iovec.iov_len, ppos);
len = vector->iov_len;
vector++;
nr_segs--;
nr = fn(filp, base, len, ppos);
if (nr < 0) { if (nr < 0) {
if (!ret) if (!ret)
...@@ -752,8 +743,9 @@ static ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov, ...@@ -752,8 +743,9 @@ static ssize_t do_loop_readv_writev(struct file *filp, struct iovec *iov,
break; break;
} }
ret += nr; ret += nr;
if (nr != len) if (nr != iovec.iov_len)
break; break;
iov_iter_advance(iter, nr);
} }
return ret; return ret;
...@@ -844,6 +836,7 @@ static ssize_t do_readv_writev(int type, struct file *file, ...@@ -844,6 +836,7 @@ static ssize_t do_readv_writev(int type, struct file *file,
size_t tot_len; size_t tot_len;
struct iovec iovstack[UIO_FASTIOV]; struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov = iovstack; struct iovec *iov = iovstack;
struct iov_iter iter;
ssize_t ret; ssize_t ret;
io_fn_t fn; io_fn_t fn;
iov_fn_t fnv; iov_fn_t fnv;
...@@ -853,6 +846,7 @@ static ssize_t do_readv_writev(int type, struct file *file, ...@@ -853,6 +846,7 @@ static ssize_t do_readv_writev(int type, struct file *file,
ARRAY_SIZE(iovstack), iovstack, &iov); ARRAY_SIZE(iovstack), iovstack, &iov);
if (ret <= 0) if (ret <= 0)
goto out; goto out;
iov_iter_init(&iter, type, iov, nr_segs, ret);
tot_len = ret; tot_len = ret;
ret = rw_verify_area(type, file, pos, tot_len); ret = rw_verify_area(type, file, pos, tot_len);
...@@ -872,13 +866,11 @@ static ssize_t do_readv_writev(int type, struct file *file, ...@@ -872,13 +866,11 @@ static ssize_t do_readv_writev(int type, struct file *file,
} }
if (iter_fn) if (iter_fn)
ret = do_iter_readv_writev(file, type, iov, nr_segs, tot_len, ret = do_iter_readv_writev(file, &iter, pos, iter_fn);
pos, iter_fn);
else if (fnv) else if (fnv)
ret = do_sync_readv_writev(file, iov, nr_segs, tot_len, ret = do_sync_readv_writev(file, &iter, pos, fnv);
pos, fnv);
else else
ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn); ret = do_loop_readv_writev(file, &iter, pos, fn);
if (type != READ) if (type != READ)
file_end_write(file); file_end_write(file);
...@@ -1024,6 +1016,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, ...@@ -1024,6 +1016,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
compat_ssize_t tot_len; compat_ssize_t tot_len;
struct iovec iovstack[UIO_FASTIOV]; struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov = iovstack; struct iovec *iov = iovstack;
struct iov_iter iter;
ssize_t ret; ssize_t ret;
io_fn_t fn; io_fn_t fn;
iov_fn_t fnv; iov_fn_t fnv;
...@@ -1033,6 +1026,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, ...@@ -1033,6 +1026,7 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
UIO_FASTIOV, iovstack, &iov); UIO_FASTIOV, iovstack, &iov);
if (ret <= 0) if (ret <= 0)
goto out; goto out;
iov_iter_init(&iter, type, iov, nr_segs, ret);
tot_len = ret; tot_len = ret;
ret = rw_verify_area(type, file, pos, tot_len); 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, ...@@ -1052,13 +1046,11 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
} }
if (iter_fn) if (iter_fn)
ret = do_iter_readv_writev(file, type, iov, nr_segs, tot_len, ret = do_iter_readv_writev(file, &iter, pos, iter_fn);
pos, iter_fn);
else if (fnv) else if (fnv)
ret = do_sync_readv_writev(file, iov, nr_segs, tot_len, ret = do_sync_readv_writev(file, &iter, pos, fnv);
pos, fnv);
else else
ret = do_loop_readv_writev(file, iov, nr_segs, pos, fn); ret = do_loop_readv_writev(file, &iter, pos, fn);
if (type != READ) if (type != READ)
file_end_write(file); file_end_write(file);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment