@@ -1477,24 +1477,20 @@ static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb)
return 0;
}
-static ssize_t aio_setup_rw(int rw, const struct iocb *iocb,
- struct iovec **iovec, bool vectored, bool compat,
+static struct iovec *aio_setup_rw(int rw, const struct iocb *iocb,
+ struct iovec_cache *cache, bool vectored, bool compat,
struct iov_iter *iter)
{
void __user *buf = (void __user *)(uintptr_t)iocb->aio_buf;
size_t len = iocb->aio_nbytes;
- if (!vectored) {
- ssize_t ret = import_single_range(rw, buf, len, *iovec, iter);
- *iovec = NULL;
- return ret;
- }
+ if (!vectored)
+ return ERR_PTR(import_single_range(rw, buf, len, cache->iov, iter));
#ifdef CONFIG_COMPAT
if (compat)
- return compat_import_iovec(rw, buf, len, UIO_FASTIOV, iovec,
- iter);
+ return compat_iovec_import(rw, buf, len, cache, iter);
#endif
- return import_iovec(rw, buf, len, UIO_FASTIOV, iovec, iter);
+ return iovec_import(rw, buf, len, cache, iter);
}
static inline void aio_rw_done(struct kiocb *req, ssize_t ret)
@@ -1520,8 +1516,9 @@ static inline void aio_rw_done(struct kiocb *req, ssize_t ret)
static int aio_read(struct kiocb *req, const struct iocb *iocb,
bool vectored, bool compat)
{
- struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs;
+ struct iovec_cache cache;
struct iov_iter iter;
+ struct iovec *iovec;
struct file *file;
int ret;
@@ -1535,9 +1532,9 @@ static int aio_read(struct kiocb *req, const struct iocb *iocb,
if (unlikely(!file->f_op->read_iter))
return -EINVAL;
- ret = aio_setup_rw(READ, iocb, &iovec, vectored, compat, &iter);
- if (ret < 0)
- return ret;
+ iovec = aio_setup_rw(READ, iocb, &cache, vectored, compat, &iter);
+ if (IS_ERR(iovec))
+ return PTR_ERR(iovec);
ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter));
if (!ret)
aio_rw_done(req, call_read_iter(file, req, &iter));
@@ -1548,8 +1545,9 @@ static int aio_read(struct kiocb *req, const struct iocb *iocb,
static int aio_write(struct kiocb *req, const struct iocb *iocb,
bool vectored, bool compat)
{
- struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs;
+ struct iovec_cache cache;
struct iov_iter iter;
+ struct iovec *iovec;
struct file *file;
int ret;
@@ -1563,9 +1561,9 @@ static int aio_write(struct kiocb *req, const struct iocb *iocb,
if (unlikely(!file->f_op->write_iter))
return -EINVAL;
- ret = aio_setup_rw(WRITE, iocb, &iovec, vectored, compat, &iter);
- if (ret < 0)
- return ret;
+ iovec = aio_setup_rw(WRITE, iocb, &cache, vectored, compat, &iter);
+ if (IS_ERR(iovec))
+ return PTR_ERR(iovec);
ret = rw_verify_area(WRITE, file, &req->ki_pos, iov_iter_count(&iter));
if (!ret) {
/*
@@ -884,35 +884,38 @@ EXPORT_SYMBOL(vfs_iter_write);
ssize_t vfs_readv(struct file *file, const struct iovec __user *vec,
unsigned long vlen, loff_t *pos, rwf_t flags)
{
- struct iovec iovstack[UIO_FASTIOV];
- struct iovec *iov = iovstack;
+ struct iovec_cache cache;
struct iov_iter iter;
+ struct iovec *iov;
ssize_t ret;
- ret = import_iovec(READ, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
- if (ret >= 0) {
- ret = do_iter_read(file, &iter, pos, flags);
- kfree(iov);
- }
+ iov = iovec_import(READ, vec, vlen, &cache, &iter);
+ if (IS_ERR(iov))
+ return PTR_ERR(iov);
+
+ ret = do_iter_read(file, &iter, pos, flags);
+ kfree(iov);
return ret;
}
static ssize_t vfs_writev(struct file *file, const struct iovec __user *vec,
unsigned long vlen, loff_t *pos, rwf_t flags)
{
- struct iovec iovstack[UIO_FASTIOV];
- struct iovec *iov = iovstack;
+ struct iovec_cache cache;
struct iov_iter iter;
+ struct iovec *iov;
ssize_t ret;
- ret = import_iovec(WRITE, vec, vlen, ARRAY_SIZE(iovstack), &iov, &iter);
- if (ret >= 0) {
- file_start_write(file);
- ret = do_iter_write(file, &iter, pos, flags);
- file_end_write(file);
- kfree(iov);
- }
+ iov = iovec_import(WRITE, vec, vlen, &cache, &iter);
+ if (IS_ERR(iov))
+ return PTR_ERR(iov);
+
+ file_start_write(file);
+ ret = do_iter_write(file, &iter, pos, flags);
+ file_end_write(file);
+
+ kfree(iov);
return ret;
}
@@ -1073,16 +1076,17 @@ static size_t compat_readv(struct file *file,
const struct compat_iovec __user *vec,
unsigned long vlen, loff_t *pos, rwf_t flags)
{
- struct iovec iovstack[UIO_FASTIOV];
- struct iovec *iov = iovstack;
+ struct iovec_cache cache;
struct iov_iter iter;
+ struct iovec *iov;
ssize_t ret;
- ret = compat_import_iovec(READ, vec, vlen, UIO_FASTIOV, &iov, &iter);
- if (ret >= 0) {
- ret = do_iter_read(file, &iter, pos, flags);
- kfree(iov);
- }
+ iov = compat_iovec_import(READ, vec, vlen, &cache, &iter);
+ if (IS_ERR(iov))
+ return PTR_ERR(iov);
+
+ ret = do_iter_read(file, &iter, pos, flags);
+ kfree(iov);
if (ret > 0)
add_rchar(current, ret);
inc_syscr(current);
@@ -1181,18 +1185,19 @@ static size_t compat_writev(struct file *file,
const struct compat_iovec __user *vec,
unsigned long vlen, loff_t *pos, rwf_t flags)
{
- struct iovec iovstack[UIO_FASTIOV];
- struct iovec *iov = iovstack;
+ struct iovec_cache cache;
struct iov_iter iter;
+ struct iovec *iov;
ssize_t ret;
- ret = compat_import_iovec(WRITE, vec, vlen, UIO_FASTIOV, &iov, &iter);
- if (ret >= 0) {
- file_start_write(file);
- ret = do_iter_write(file, &iter, pos, flags);
- file_end_write(file);
- kfree(iov);
- }
+ iov = compat_iovec_import(WRITE, vec, vlen, &cache, &iter);
+ if (IS_ERR(iov))
+ return PTR_ERR(iov);
+
+ file_start_write(file);
+ ret = do_iter_write(file, &iter, pos, flags);
+ file_end_write(file);
+ kfree(iov);
if (ret > 0)
add_wchar(current, ret);
inc_syscw(current);
@@ -1349,9 +1349,9 @@ static long do_vmsplice(struct file *f, struct iov_iter *iter, unsigned int flag
SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov,
unsigned long, nr_segs, unsigned int, flags)
{
- struct iovec iovstack[UIO_FASTIOV];
- struct iovec *iov = iovstack;
+ struct iovec_cache cache;
struct iov_iter iter;
+ struct iovec *iov;
ssize_t error;
struct fd f;
int type;
@@ -1361,9 +1361,10 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov,
if (error)
return error;
- error = import_iovec(type, uiov, nr_segs,
- ARRAY_SIZE(iovstack), &iov, &iter);
- if (error >= 0) {
+ iov = iovec_import(type, uiov, nr_segs, &cache, &iter);
+ if (IS_ERR(iov)) {
+ error = PTR_ERR(iov);
+ } else {
error = do_vmsplice(f.file, &iter, flags);
kfree(iov);
}
@@ -1375,9 +1376,9 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov,
COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, iov32,
unsigned int, nr_segs, unsigned int, flags)
{
- struct iovec iovstack[UIO_FASTIOV];
- struct iovec *iov = iovstack;
+ struct iovec_cache cache;
struct iov_iter iter;
+ struct iovec *iov;
ssize_t error;
struct fd f;
int type;
@@ -1387,9 +1388,10 @@ COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, io
if (error)
return error;
- error = compat_import_iovec(type, iov32, nr_segs,
- ARRAY_SIZE(iovstack), &iov, &iter);
- if (error >= 0) {
+ iov = compat_iovec_import(type, iov32, nr_segs, &cache, &iter);
+ if (IS_ERR(iov)) {
+ error = PTR_ERR(iov);
+ } else {
error = do_vmsplice(f.file, &iter, flags);
kfree(iov);
}
iovec_import() has a safer calling convention than import_iovec(). Signed-off-by: David Laight <david.laight@aculab.com> --- fs/aio.c | 34 ++++++++++++------------ fs/read_write.c | 69 ++++++++++++++++++++++++++----------------------- fs/splice.c | 22 +++++++++------- 3 files changed, 65 insertions(+), 60 deletions(-)