|
@@ -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,
|
|
|
|
- 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 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,
|
|
|
|
- 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;
|
|
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,
|
|
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,
|
|
|
|
- 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;
|
|
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;
|
|
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 (nr < 0) {
|
|
if (!ret)
|
|
if (!ret)
|
|
@@ -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,
|
|
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,
|
|
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,
|
|
}
|
|
}
|
|
|
|
|
|
if (iter_fn)
|
|
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)
|
|
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
|
|
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,
|
|
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,
|
|
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,
|
|
}
|
|
}
|
|
|
|
|
|
if (iter_fn)
|
|
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)
|
|
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
|
|
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);
|