Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ac15ac06 authored by Al Viro's avatar Al Viro
Browse files

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
Loading
Loading
Loading
Loading
+23 −31
Original line number Diff line number Diff line
@@ -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);