Re: 2.0.30 serial.c, ppp.c and pppd-2.2 questions

Bill Hawes (whawes@star.net)
Mon, 21 Jul 1997 18:25:01 -0400


This is a multi-part message in MIME format.
--------------F53FEA3CF2D0BEFEC90543ED
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Hi Rob,

After studying your flip buffer overflow problem for a while, I have a
theory that might explain why it's overflowing.

The flip buffer is flipped on the timer queue, and when the n_tty.c code
needs to exclude input briefly, it disables the timer queue. Under
heavy paging load, the system may have to service page faults while the
timer queue is disabled. This means there's a slight probability that
the timer queue would be disabled at the jiffy tick, so it might miss a
turn.

This small probability could become significant if you have many ttys in
use; if any tty gets a page fault with the queue disabled, _all_ ttys
might lose their turn to flip the buffer. (Even ptys disable the timer,
and they don't even use the flip buffer!). I did a test a while back to
see what sections of code are interrupted by page faults while in
copy_xx_user, and n_tty.c was second only after pipe.c in interruptions.

I've put together a small patch against 2.0.30 to test this out. It
works by defining a per-tty disable count, so that instead of disabling
the whole timer queue, only the flip code for one tty is disabled. I've
tested it thoroughly for at least 30 seconds, and it didn't break
anything :-) So if you feel like experimenting, this may help with the
overflow problems ...

Perhaps others can comment on this, but to me it makes much more sense
for a tty to disable only its own flip buffer.

Regards,
Bill
--------------F53FEA3CF2D0BEFEC90543ED
Content-Type: text/plain; charset=us-ascii; name="flip_30-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="flip_30-patch"

--- linux-2.0.30/drivers/char/n_tty.c.old Mon Sep 2 08:18:26 1996
+++ linux-2.0.30/drivers/char/n_tty.c Mon Jul 21 17:47:39 1997
@@ -40,6 +40,9 @@

#define CONSOLE_DEV MKDEV(TTY_MAJOR,0)

+#define disable_flip(tty) (tty)->flip.disabled++;
+#define enable_flip(tty) (tty)->flip.disabled--;
+
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
@@ -859,9 +862,9 @@
while (1) {
int eol;

- disable_bh(TQUEUE_BH);
+ disable_flip(tty);
if (!tty->read_cnt) {
- enable_bh(TQUEUE_BH);
+ enable_flip(tty);
break;
}
eol = clear_bit(tty->read_tail,
@@ -870,7 +873,7 @@
tty->read_tail = ((tty->read_tail+1) &
(N_TTY_BUF_SIZE-1));
tty->read_cnt--;
- enable_bh(TQUEUE_BH);
+ enable_flip(tty);
if (!eol) {
put_user(c, b++);
if (--nr)
@@ -887,10 +890,10 @@
break;
}
} else {
- disable_bh(TQUEUE_BH);
+ disable_flip(tty);
copy_from_read_buf(tty, &b, &nr);
copy_from_read_buf(tty, &b, &nr);
- enable_bh(TQUEUE_BH);
+ enable_flip(tty);
}

/* If there is enough space in the read buffer now, let the
--- linux-2.0.30/drivers/char/tty_io.c.old Thu Oct 31 07:34:58 1996
+++ linux-2.0.30/drivers/char/tty_io.c Mon Jul 21 17:42:35 1997
@@ -1721,6 +1721,12 @@
char *fp;
int count;

+ /*
+ * Check the disabled count
+ */
+ if (tty->flip.disabled)
+ return;
+
if (tty->flip.buf_num) {
cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
--- linux-2.0.30/include/linux/tty.h.old Sun Apr 27 16:22:13 1997
+++ linux-2.0.30/include/linux/tty.h Mon Jul 21 17:44:17 1997
@@ -96,6 +96,7 @@
unsigned char *flag_buf_ptr;
int count;
int buf_num;
+ int disabled;
};

/*

--------------F53FEA3CF2D0BEFEC90543ED--