lift iov_iter into {compat_,}do_readv_writev()

get it closer to matching {compat_,}rw_copy_check_uvector().

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2015-03-20 20:10:21 -04:00
Родитель c0fec3a98b
Коммит ac15ac0669
1 изменённых файлов: 23 добавлений и 31 удалений

Просмотреть файл

@ -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);