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

new iov_iter flavour - ITER_UBUF



Equivalent of single-segment iovec.  Initialized by iov_iter_ubuf(),
checked for by iter_is_ubuf(), otherwise behaves like ITER_IOVEC
ones.

We are going to expose the things like ->write_iter() et.al. to those
in subsequent commits.

New predicate (user_backed_iter()) that is true for ITER_IOVEC and
ITER_UBUF; places like direct-IO handling should use that for
checking that pages we modify after getting them from iov_iter_get_pages()
would need to be dirtied.

DO NOT assume that replacing iter_is_iovec() with user_backed_iter()
will solve all problems - there's code that uses iter_is_iovec() to
decide how to poke around in iov_iter guts and for that the predicate
replacement obviously won't suffice.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent fa9db655
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ static ssize_t __blkdev_direct_IO_simple(struct kiocb *iocb,

	if (iov_iter_rw(iter) == READ) {
		bio_init(&bio, bdev, vecs, nr_pages, REQ_OP_READ);
		if (iter_is_iovec(iter))
		if (user_backed_iter(iter))
			should_dirty = true;
	} else {
		bio_init(&bio, bdev, vecs, nr_pages, dio_bio_write_op(iocb));
@@ -204,7 +204,7 @@ static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
	}

	dio->size = 0;
	if (is_read && iter_is_iovec(iter))
	if (is_read && user_backed_iter(iter))
		dio->flags |= DIO_SHOULD_DIRTY;

	blk_start_plug(&plug);
@@ -335,7 +335,7 @@ static ssize_t __blkdev_direct_IO_async(struct kiocb *iocb,
	dio->size = bio->bi_iter.bi_size;

	if (is_read) {
		if (iter_is_iovec(iter)) {
		if (user_backed_iter(iter)) {
			dio->flags |= DIO_SHOULD_DIRTY;
			bio_set_pages_dirty(bio);
		}
+1 −1
Original line number Diff line number Diff line
@@ -1262,7 +1262,7 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
	size_t count = iov_iter_count(iter);
	loff_t pos = iocb->ki_pos;
	bool write = iov_iter_rw(iter) == WRITE;
	bool should_dirty = !write && iter_is_iovec(iter);
	bool should_dirty = !write && user_backed_iter(iter);

	if (write && ceph_snap(file_inode(file)) != CEPH_NOSNAP)
		return -EROFS;
+1 −1
Original line number Diff line number Diff line
@@ -4004,7 +4004,7 @@ static ssize_t __cifs_readv(
	if (!is_sync_kiocb(iocb))
		ctx->iocb = iocb;

	if (iter_is_iovec(to))
	if (user_backed_iter(to))
		ctx->should_dirty = true;

	if (direct) {
+1 −1
Original line number Diff line number Diff line
@@ -1251,7 +1251,7 @@ ssize_t __blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
	spin_lock_init(&dio->bio_lock);
	dio->refcount = 1;

	dio->should_dirty = iter_is_iovec(iter) && iov_iter_rw(iter) == READ;
	dio->should_dirty = user_backed_iter(iter) && iov_iter_rw(iter) == READ;
	sdio.iter = iter;
	sdio.final_block_in_request = end >> blkbits;

+2 −2
Original line number Diff line number Diff line
@@ -1356,7 +1356,7 @@ static ssize_t fuse_dev_read(struct kiocb *iocb, struct iov_iter *to)
	if (!fud)
		return -EPERM;

	if (!iter_is_iovec(to))
	if (!user_backed_iter(to))
		return -EINVAL;

	fuse_copy_init(&cs, 1, to);
@@ -1949,7 +1949,7 @@ static ssize_t fuse_dev_write(struct kiocb *iocb, struct iov_iter *from)
	if (!fud)
		return -EPERM;

	if (!iter_is_iovec(from))
	if (!user_backed_iter(from))
		return -EINVAL;

	fuse_copy_init(&cs, 0, from);
Loading