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:
		| @@ -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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user