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

Commit 293bc982 authored by Al Viro's avatar Al Viro
Browse files

new methods: ->read_iter() and ->write_iter()



Beginning to introduce those.  Just the callers for now, and it's
clumsier than it'll eventually become; once we finish converting
aio_read and aio_write instances, the things will get nicer.

For now, these guys are in parallel to ->aio_read() and ->aio_write();
they take iocb and iov_iter, with everything in iov_iter already
validated.  File offset is passed in iocb->ki_pos, iov/nr_segs -
in iov_iter.

Main concerns in that series are stack footprint and ability to
split the damn thing cleanly.

[fix from Peter Ujfalusi <peter.ujfalusi@ti.com> folded]

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 7f7f25e8
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -430,6 +430,8 @@ prototypes:
	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
	ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
	ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
	ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
	ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
	int (*iterate) (struct file *, struct dir_context *);
	unsigned int (*poll) (struct file *, struct poll_table_struct *);
	long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
+8 −2
Original line number Diff line number Diff line
@@ -806,6 +806,8 @@ struct file_operations {
	ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
	ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
	ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
	ssize_t (*read_iter) (struct kiocb *, struct iov_iter *);
	ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
	int (*iterate) (struct file *, struct dir_context *);
	unsigned int (*poll) (struct file *, struct poll_table_struct *);
	long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
@@ -836,11 +838,15 @@ otherwise noted.

  read: called by read(2) and related system calls

  aio_read: called by io_submit(2) and other asynchronous I/O operations
  aio_read: vectored, possibly asynchronous read

  read_iter: possibly asynchronous read with iov_iter as destination

  write: called by write(2) and related system calls

  aio_write: called by io_submit(2) and other asynchronous I/O operations
  aio_write: vectored, possibly asynchronous write

  write_iter: possibly asynchronous write with iov_iter as source

  iterate: called when the VFS needs to read the directory contents

+12 −2
Original line number Diff line number Diff line
@@ -1241,6 +1241,7 @@ SYSCALL_DEFINE1(io_destroy, aio_context_t, ctx)

typedef ssize_t (aio_rw_op)(struct kiocb *, const struct iovec *,
			    unsigned long, loff_t);
typedef ssize_t (rw_iter_op)(struct kiocb *, struct iov_iter *);

static ssize_t aio_setup_vectored_rw(struct kiocb *kiocb,
				     int rw, char __user *buf,
@@ -1298,7 +1299,9 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
	int rw;
	fmode_t mode;
	aio_rw_op *rw_op;
	rw_iter_op *iter_op;
	struct iovec inline_vec, *iovec = &inline_vec;
	struct iov_iter iter;

	switch (opcode) {
	case IOCB_CMD_PREAD:
@@ -1306,6 +1309,7 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
		mode	= FMODE_READ;
		rw	= READ;
		rw_op	= file->f_op->aio_read;
		iter_op	= file->f_op->read_iter;
		goto rw_common;

	case IOCB_CMD_PWRITE:
@@ -1313,12 +1317,13 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
		mode	= FMODE_WRITE;
		rw	= WRITE;
		rw_op	= file->f_op->aio_write;
		iter_op	= file->f_op->write_iter;
		goto rw_common;
rw_common:
		if (unlikely(!(file->f_mode & mode)))
			return -EBADF;

		if (!rw_op)
		if (!rw_op && !iter_op)
			return -EINVAL;

		ret = (opcode == IOCB_CMD_PREADV ||
@@ -1347,7 +1352,12 @@ static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
		if (rw == WRITE)
			file_start_write(file);

		if (iter_op) {
			iov_iter_init(&iter, rw, iovec, nr_segs, req->ki_nbytes);
			ret = iter_op(req, &iter);
		} else {
			ret = rw_op(req, iovec, nr_segs, req->ki_pos);
		}

		if (rw == WRITE)
			file_end_write(file);
+4 −2
Original line number Diff line number Diff line
@@ -175,9 +175,11 @@ struct file *alloc_file(struct path *path, fmode_t mode,
	file->f_path = *path;
	file->f_inode = path->dentry->d_inode;
	file->f_mapping = path->dentry->d_inode->i_mapping;
	if ((mode & FMODE_READ) && likely(fop->read || fop->aio_read))
	if ((mode & FMODE_READ) &&
	     likely(fop->read || fop->aio_read || fop->read_iter))
		mode |= FMODE_CAN_READ;
	if ((mode & FMODE_WRITE) && likely(fop->write || fop->aio_write))
	if ((mode & FMODE_WRITE) &&
	     likely(fop->write || fop->aio_write || fop->write_iter))
		mode |= FMODE_CAN_WRITE;
	file->f_mode = mode;
	file->f_op = fop;
+4 −2
Original line number Diff line number Diff line
@@ -725,9 +725,11 @@ static int do_dentry_open(struct file *f,
	}
	if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
		i_readcount_inc(inode);
	if ((f->f_mode & FMODE_READ) && likely(f->f_op->read || f->f_op->aio_read))
	if ((f->f_mode & FMODE_READ) &&
	     likely(f->f_op->read || f->f_op->aio_read || f->f_op->read_iter))
		f->f_mode |= FMODE_CAN_READ;
	if ((f->f_mode & FMODE_WRITE) && likely(f->f_op->write || f->f_op->aio_write))
	if ((f->f_mode & FMODE_WRITE) &&
	     likely(f->f_op->write || f->f_op->aio_write || f->f_op->write_iter))
		f->f_mode |= FMODE_CAN_WRITE;

	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
Loading