lkml.org 
[lkml]   [2009]   [Jul]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: [PATCH] kdesu broken


On Mon, 27 Jul 2009, Alan Cox wrote:
>
> It's theoretically imperfect in the case where you write a vast amount of
> output in one go, the tty is blocked the other end and then you close.
> However in practice that doesn't happen because with tty->low_latency = 1
> we run the pty received n_tty ldisc code in our context so each write
> fires through the entire n_tty ldisc and does flow control synchronously.

An alternative might be something like this.

THIS IS TOTALLY UNTESTED.

This is just meant as a "this kind of approach may be a good idea", and
just tries to make sure that any delayed work is flushed by closing the
tty.

No guarantees. It may or may not compile. It may or may not make any
difference. It might do unspeakable things to your pets. It really is
meant to be an example of what a "flush" function could/should do. There
are probably other things/buffers that may need flushing.

Linus

---
drivers/char/tty_io.c | 33 +++++++++++++++++++++++++++++++++
1 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index a3afa0c..1be69af 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -143,6 +143,7 @@ ssize_t redirected_tty_write(struct file *, const char __user *,
static unsigned int tty_poll(struct file *, poll_table *);
static int tty_open(struct inode *, struct file *);
static int tty_release(struct inode *, struct file *);
+static int tty_flush(struct file *filp, fl_owner_t id);
long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
#ifdef CONFIG_COMPAT
static long tty_compat_ioctl(struct file *file, unsigned int cmd,
@@ -415,6 +416,7 @@ static const struct file_operations tty_fops = {
.unlocked_ioctl = tty_ioctl,
.compat_ioctl = tty_compat_ioctl,
.open = tty_open,
+ .flush = tty_flush,
.release = tty_release,
.fasync = tty_fasync,
};
@@ -1831,7 +1833,38 @@ static int tty_open(struct inode *inode, struct file *filp)
return ret;
}

+/* This should probably be a generic function */
+static void flush_delayed_work(struct delayed_work *work)
+{
+ if (cancel_delayed_work(work)) {
+ schedule_delayed_work(work, 0);
+ flush_scheduled_work();
+ }
+}

+/**
+ * tty_flush - vfs callback for close
+ * @filp: file pointer for handle to tty
+ * @id: struct files_struct of owner.
+ *
+ * Called for every close(), whether the last or not
+ */
+static int tty_flush(struct file *filp, fl_owner_t id)
+{
+ struct tty_struct *tty, *o_tty;
+ struct inode *inode;
+
+ inode = filp->f_path.dentry->d_inode;
+ tty = (struct tty_struct *)filp->private_data;
+
+ if (tty_paranoia_check(tty, inode, "tty_flush"))
+ return 0;
+
+ o_tty = tty->link;
+ if (o_tty)
+ flush_delayed_work(&o_tty->buf.work);
+ return 0;
+}


/**


\
 
 \ /
  Last update: 2009-10-18 23:28    [W:0.121 / U:0.148 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site