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:
Родитель
c0fec3a98b
Коммит
ac15ac0669
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче