diff options
author | Alan Cox <alan@linux.intel.com> | 2009-07-07 11:39:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-07-08 12:47:59 -0400 |
commit | d945cb9cce20ac7143c2de8d88b187f62db99bdc (patch) | |
tree | 88f8cc4b4e545c4e8ce998c9400767fffe5ddc94 /drivers/char | |
parent | b4b21cac88caa4078f5755b0bd3770af5fe9c146 (diff) |
pty: Rework the pty layer to use the normal buffering logic
This fixes the ppp problems and various other issues with call locking
caused by one side of a pty called in one locking context trying to match
another with differing rules on the other side. We also get a big slack
space to work with that means we can bury the flow control deadlock case
for any conceivable real world situation.
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/pty.c | 154 |
1 files changed, 59 insertions, 95 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index daebe1ba43d4..9d1b4f548f67 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -75,114 +75,88 @@ static void pty_close(struct tty_struct *tty, struct file *filp) | |||
75 | */ | 75 | */ |
76 | static void pty_unthrottle(struct tty_struct *tty) | 76 | static void pty_unthrottle(struct tty_struct *tty) |
77 | { | 77 | { |
78 | struct tty_struct *o_tty = tty->link; | 78 | tty_wakeup(tty->link); |
79 | |||
80 | if (!o_tty) | ||
81 | return; | ||
82 | |||
83 | tty_wakeup(o_tty); | ||
84 | set_bit(TTY_THROTTLED, &tty->flags); | 79 | set_bit(TTY_THROTTLED, &tty->flags); |
85 | } | 80 | } |
86 | 81 | ||
87 | /* | 82 | /** |
88 | * WSH 05/24/97: modified to | 83 | * pty_space - report space left for writing |
89 | * (1) use space in tty->flip instead of a shared temp buffer | 84 | * @to: tty we are writing into |
90 | * The flip buffers aren't being used for a pty, so there's lots | ||
91 | * of space available. The buffer is protected by a per-pty | ||
92 | * semaphore that should almost never come under contention. | ||
93 | * (2) avoid redundant copying for cases where count >> receive_room | ||
94 | * N.B. Calls from user space may now return an error code instead of | ||
95 | * a count. | ||
96 | * | 85 | * |
97 | * FIXME: Our pty_write method is called with our ldisc lock held but | 86 | * The tty buffers allow 64K but we sneak a peak and clip at 8K this |
98 | * not our partners. We can't just wait on the other one blindly without | 87 | * allows a lot of overspill room for echo and other fun messes to |
99 | * risking deadlocks. At some point when everything has settled down we need | 88 | * be handled properly |
100 | * to look into making pty_write at least able to sleep over an ldisc change. | 89 | */ |
90 | |||
91 | static int pty_space(struct tty_struct *to) | ||
92 | { | ||
93 | int n = 8192 - to->buf.memory_used; | ||
94 | if (n < 0) | ||
95 | return 0; | ||
96 | return n; | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * pty_write - write to a pty | ||
101 | * @tty: the tty we write from | ||
102 | * @buf: kernel buffer of data | ||
103 | * @count: bytes to write | ||
101 | * | 104 | * |
102 | * The return on no ldisc is a bit counter intuitive but the logic works | 105 | * Our "hardware" write method. Data is coming from the ldisc which |
103 | * like this. During an ldisc change the other end will flush its buffers. We | 106 | * may be in a non sleeping state. We simply throw this at the other |
104 | * thus return the full length which is identical to the case where we had | 107 | * end of the link as if we were an IRQ handler receiving stuff for |
105 | * proper locking and happened to queue the bytes just before the flush during | 108 | * the other side of the pty/tty pair. |
106 | * the ldisc change. | ||
107 | */ | 109 | */ |
110 | |||
108 | static int pty_write(struct tty_struct *tty, const unsigned char *buf, | 111 | static int pty_write(struct tty_struct *tty, const unsigned char *buf, |
109 | int count) | 112 | int count) |
110 | { | 113 | { |
111 | struct tty_struct *to = tty->link; | 114 | struct tty_struct *to = tty->link; |
112 | struct tty_ldisc *ld; | 115 | int c; |
113 | int c = count; | ||
114 | 116 | ||
115 | if (!to || tty->stopped) | 117 | if (tty->stopped) |
116 | return 0; | 118 | return 0; |
117 | ld = tty_ldisc_ref(to); | 119 | |
118 | 120 | /* This isn't locked but our 8K is quite sloppy so no | |
119 | if (ld) { | 121 | big deal */ |
120 | c = to->receive_room; | 122 | |
121 | if (c > count) | 123 | c = pty_space(to); |
122 | c = count; | 124 | if (c > count) |
123 | ld->ops->receive_buf(to, buf, NULL, c); | 125 | c = count; |
124 | tty_ldisc_deref(ld); | 126 | if (c > 0) { |
127 | /* Stuff the data into the input queue of the other end */ | ||
128 | c = tty_insert_flip_string(to, buf, c); | ||
129 | /* And shovel */ | ||
130 | tty_flip_buffer_push(to); | ||
131 | tty_wakeup(tty); | ||
125 | } | 132 | } |
126 | return c; | 133 | return c; |
127 | } | 134 | } |
128 | 135 | ||
136 | /** | ||
137 | * pty_write_room - write space | ||
138 | * @tty: tty we are writing from | ||
139 | * | ||
140 | * Report how many bytes the ldisc can send into the queue for | ||
141 | * the other device. | ||
142 | */ | ||
143 | |||
129 | static int pty_write_room(struct tty_struct *tty) | 144 | static int pty_write_room(struct tty_struct *tty) |
130 | { | 145 | { |
131 | struct tty_struct *to = tty->link; | 146 | return pty_space(tty->link); |
132 | |||
133 | if (!to || tty->stopped) | ||
134 | return 0; | ||
135 | |||
136 | return to->receive_room; | ||
137 | } | 147 | } |
138 | 148 | ||
139 | /* | 149 | /** |
140 | * WSH 05/24/97: Modified for asymmetric MASTER/SLAVE behavior | 150 | * pty_chars_in_buffer - characters currently in our tx queue |
141 | * The chars_in_buffer() value is used by the ldisc select() function | 151 | * @tty: our tty |
142 | * to hold off writing when chars_in_buffer > WAKEUP_CHARS (== 256). | ||
143 | * The pty driver chars_in_buffer() Master/Slave must behave differently: | ||
144 | * | ||
145 | * The Master side needs to allow typed-ahead commands to accumulate | ||
146 | * while being canonicalized, so we report "our buffer" as empty until | ||
147 | * some threshold is reached, and then report the count. (Any count > | ||
148 | * WAKEUP_CHARS is regarded by select() as "full".) To avoid deadlock | ||
149 | * the count returned must be 0 if no canonical data is available to be | ||
150 | * read. (The N_TTY ldisc.chars_in_buffer now knows this.) | ||
151 | * | 152 | * |
152 | * The Slave side passes all characters in raw mode to the Master side's | 153 | * Report how much we have in the transmit queue. As everything is |
153 | * buffer where they can be read immediately, so in this case we can | 154 | * instantly at the other end this is easy to implement. |
154 | * return the true count in the buffer. | ||
155 | */ | 155 | */ |
156 | |||
156 | static int pty_chars_in_buffer(struct tty_struct *tty) | 157 | static int pty_chars_in_buffer(struct tty_struct *tty) |
157 | { | 158 | { |
158 | struct tty_struct *to = tty->link; | 159 | return 0; |
159 | struct tty_ldisc *ld; | ||
160 | int count = 0; | ||
161 | |||
162 | /* We should get the line discipline lock for "tty->link" */ | ||
163 | if (!to) | ||
164 | return 0; | ||
165 | /* We cannot take a sleeping reference here without deadlocking with | ||
166 | an ldisc change - but it doesn't really matter */ | ||
167 | ld = tty_ldisc_ref(to); | ||
168 | if (ld == NULL) | ||
169 | return 0; | ||
170 | |||
171 | /* The ldisc must report 0 if no characters available to be read */ | ||
172 | if (ld->ops->chars_in_buffer) | ||
173 | count = ld->ops->chars_in_buffer(to); | ||
174 | |||
175 | tty_ldisc_deref(ld); | ||
176 | |||
177 | if (tty->driver->subtype == PTY_TYPE_SLAVE) | ||
178 | return count; | ||
179 | |||
180 | /* Master side driver ... if the other side's read buffer is less than | ||
181 | * half full, return 0 to allow writers to proceed; otherwise return | ||
182 | * the count. This leaves a comfortable margin to avoid overflow, | ||
183 | * and still allows half a buffer's worth of typed-ahead commands. | ||
184 | */ | ||
185 | return (count < N_TTY_BUF_SIZE/2) ? 0 : count; | ||
186 | } | 160 | } |
187 | 161 | ||
188 | /* Set the lock flag on a pty */ | 162 | /* Set the lock flag on a pty */ |
@@ -202,20 +176,10 @@ static void pty_flush_buffer(struct tty_struct *tty) | |||
202 | { | 176 | { |
203 | struct tty_struct *to = tty->link; | 177 | struct tty_struct *to = tty->link; |
204 | unsigned long flags; | 178 | unsigned long flags; |
205 | struct tty_ldisc *ld; | ||
206 | 179 | ||
207 | if (!to) | 180 | if (!to) |
208 | return; | 181 | return; |
209 | ld = tty_ldisc_ref(to); | 182 | /* tty_buffer_flush(to); FIXME */ |
210 | |||
211 | /* The other end is changing discipline */ | ||
212 | if (!ld) | ||
213 | return; | ||
214 | |||
215 | if (ld->ops->flush_buffer) | ||
216 | to->ldisc->ops->flush_buffer(to); | ||
217 | tty_ldisc_deref(ld); | ||
218 | |||
219 | if (to->packet) { | 183 | if (to->packet) { |
220 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 184 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
221 | tty->ctrl_status |= TIOCPKT_FLUSHWRITE; | 185 | tty->ctrl_status |= TIOCPKT_FLUSHWRITE; |