Commit 494e63ee authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge 9bb48c82 ("tty: implement write_iter") into tty-linus



We want the single "splice/sendfile to a tty" regression fix into
tty-linus so it can get into 5.11-final, while the larger patch series
fixing "splice/sendfile from a tty" should wait for 5.12-rc1 so that we
get more testing.

Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parents 54ca955b 9bb48c82
Loading
Loading
Loading
Loading
+26 −22
Original line number Diff line number Diff line
@@ -143,9 +143,8 @@ LIST_HEAD(tty_drivers); /* linked list of tty drivers */
DEFINE_MUTEX(tty_mutex);

static ssize_t tty_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t tty_write(struct file *, const char __user *, size_t, loff_t *);
ssize_t redirected_tty_write(struct file *, const char __user *,
							size_t, loff_t *);
static ssize_t tty_write(struct kiocb *, struct iov_iter *);
ssize_t redirected_tty_write(struct kiocb *, struct iov_iter *);
static __poll_t tty_poll(struct file *, poll_table *);
static int tty_open(struct inode *, struct file *);
long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
@@ -478,7 +477,8 @@ static void tty_show_fdinfo(struct seq_file *m, struct file *file)
static const struct file_operations tty_fops = {
	.llseek		= no_llseek,
	.read		= tty_read,
	.write		= tty_write,
	.write_iter	= tty_write,
	.splice_write	= iter_file_splice_write,
	.poll		= tty_poll,
	.unlocked_ioctl	= tty_ioctl,
	.compat_ioctl	= tty_compat_ioctl,
@@ -491,7 +491,8 @@ static const struct file_operations tty_fops = {
static const struct file_operations console_fops = {
	.llseek		= no_llseek,
	.read		= tty_read,
	.write		= redirected_tty_write,
	.write_iter	= redirected_tty_write,
	.splice_write	= iter_file_splice_write,
	.poll		= tty_poll,
	.unlocked_ioctl	= tty_ioctl,
	.compat_ioctl	= tty_compat_ioctl,
@@ -606,9 +607,9 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session)
	/* This breaks for file handles being sent over AF_UNIX sockets ? */
	list_for_each_entry(priv, &tty->tty_files, list) {
		filp = priv->file;
		if (filp->f_op->write == redirected_tty_write)
		if (filp->f_op->write_iter == redirected_tty_write)
			cons_filp = filp;
		if (filp->f_op->write != tty_write)
		if (filp->f_op->write_iter != tty_write)
			continue;
		closecount++;
		__tty_fasync(-1, filp, 0);	/* can't block */
@@ -901,9 +902,9 @@ static inline ssize_t do_tty_write(
	ssize_t (*write)(struct tty_struct *, struct file *, const unsigned char *, size_t),
	struct tty_struct *tty,
	struct file *file,
	const char __user *buf,
	size_t count)
	struct iov_iter *from)
{
	size_t count = iov_iter_count(from);
	ssize_t ret, written = 0;
	unsigned int chunk;

@@ -955,14 +956,20 @@ static inline ssize_t do_tty_write(
		size_t size = count;
		if (size > chunk)
			size = chunk;

		ret = -EFAULT;
		if (copy_from_user(tty->write_buf, buf, size))
		if (copy_from_iter(tty->write_buf, size, from) != size)
			break;

		ret = write(tty, file, tty->write_buf, size);
		if (ret <= 0)
			break;

		/* FIXME! Have Al check this! */
		if (ret != size)
			iov_iter_revert(from, size-ret);

		written += ret;
		buf += ret;
		count -= ret;
		if (!count)
			break;
@@ -1022,9 +1029,9 @@ void tty_write_message(struct tty_struct *tty, char *msg)
 *	write method will not be invoked in parallel for each device.
 */

static ssize_t tty_write(struct file *file, const char __user *buf,
						size_t count, loff_t *ppos)
static ssize_t tty_write(struct kiocb *iocb, struct iov_iter *from)
{
	struct file *file = iocb->ki_filp;
	struct tty_struct *tty = file_tty(file);
 	struct tty_ldisc *ld;
	ssize_t ret;
@@ -1037,18 +1044,15 @@ static ssize_t tty_write(struct file *file, const char __user *buf,
	if (tty->ops->write_room == NULL)
		tty_err(tty, "missing write_room method\n");
	ld = tty_ldisc_ref_wait(tty);
	if (!ld)
		return hung_up_tty_write(file, buf, count, ppos);
	if (!ld->ops->write)
	if (!ld || !ld->ops->write)
		ret = -EIO;
	else
		ret = do_tty_write(ld->ops->write, tty, file, buf, count);
		ret = do_tty_write(ld->ops->write, tty, file, from);
	tty_ldisc_deref(ld);
	return ret;
}

ssize_t redirected_tty_write(struct file *file, const char __user *buf,
						size_t count, loff_t *ppos)
ssize_t redirected_tty_write(struct kiocb *iocb, struct iov_iter *iter)
{
	struct file *p = NULL;

@@ -1059,11 +1063,11 @@ ssize_t redirected_tty_write(struct file *file, const char __user *buf,

	if (p) {
		ssize_t res;
		res = vfs_write(p, buf, count, &p->f_pos);
		res = vfs_iocb_iter_write(p, iocb, iter);
		fput(p);
		return res;
	}
	return tty_write(file, buf, count, ppos);
	return tty_write(iocb, iter);
}

/*
@@ -2295,7 +2299,7 @@ static int tioccons(struct file *file)
{
	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;
	if (file->f_op->write == redirected_tty_write) {
	if (file->f_op->write_iter == redirected_tty_write) {
		struct file *f;
		spin_lock(&redirect_lock);
		f = redirect;