hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/tty/tty_ioctl.c
....@@ -21,6 +21,7 @@
2121 #include <linux/bitops.h>
2222 #include <linux/mutex.h>
2323 #include <linux/compat.h>
24
+#include "tty.h"
2425
2526 #include <asm/io.h>
2627 #include <linux/uaccess.h>
....@@ -397,21 +398,42 @@
397398 tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
398399 tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
399400
400
- ld = tty_ldisc_ref(tty);
401
+ if (opt & (TERMIOS_FLUSH|TERMIOS_WAIT)) {
402
+retry_write_wait:
403
+ retval = wait_event_interruptible(tty->write_wait, !tty_chars_in_buffer(tty));
404
+ if (retval < 0)
405
+ return retval;
401406
402
- if (ld != NULL) {
403
- if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
404
- ld->ops->flush_buffer(tty);
405
- tty_ldisc_deref(ld);
407
+ if (tty_write_lock(tty, 0) < 0)
408
+ goto retry_write_wait;
409
+
410
+ /* Racing writer? */
411
+ if (tty_chars_in_buffer(tty)) {
412
+ tty_write_unlock(tty);
413
+ goto retry_write_wait;
414
+ }
415
+
416
+ ld = tty_ldisc_ref(tty);
417
+ if (ld != NULL) {
418
+ if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
419
+ ld->ops->flush_buffer(tty);
420
+ tty_ldisc_deref(ld);
421
+ }
422
+
423
+ if ((opt & TERMIOS_WAIT) && tty->ops->wait_until_sent) {
424
+ tty->ops->wait_until_sent(tty, 0);
425
+ if (signal_pending(current)) {
426
+ tty_write_unlock(tty);
427
+ return -ERESTARTSYS;
428
+ }
429
+ }
430
+
431
+ tty_set_termios(tty, &tmp_termios);
432
+
433
+ tty_write_unlock(tty);
434
+ } else {
435
+ tty_set_termios(tty, &tmp_termios);
406436 }
407
-
408
- if (opt & TERMIOS_WAIT) {
409
- tty_wait_until_sent(tty, 0);
410
- if (signal_pending(current))
411
- return -ERESTARTSYS;
412
- }
413
-
414
- tty_set_termios(tty, &tmp_termios);
415437
416438 /* FIXME: Arguably if tmp_termios == tty->termios AND the
417439 actual requested termios was not tmp_termios then we may