lkml.org 
[lkml]   [1997]   [Jul]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: 2.0.30 serial.c, ppp.c and pppd-2.2 questions
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--- 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;
};

/*
\
 
 \ /
  Last update: 2005-03-22 13:39    [W:0.132 / U:0.264 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site