summaryrefslogtreecommitdiffstats
path: root/drivers/tty/n_tty.c
AgeCommit message (Collapse)Author
2013-07-23n_tty: Move buffers into n_tty_dataPeter Hurley
Reduce pointer reloading and improve locality-of-reference; allocate read_buf and echo_buf within struct n_tty_data. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Remove alias ptrs in __receive_buf()Peter Hurley
The char and flag buffer local alias pointers, p and f, are unnecessary; remove them. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Fix EOF push handlingPeter Hurley
In canonical mode, an EOF which is not the first character of the line causes read() to complete and return the number of characters read so far (commonly referred to as EOF push). However, if the previous read() returned because the user buffer was full _and_ the next character is an EOF not at the beginning of the line, read() must not return 0, thus mistakenly indicating the end-of-file condition. The TTY_PUSH flag is used to indicate an EOF was received which is not at the beginning of the line. Because the EOF push condition is evaluated by a thread other than the read(), multiple EOF pushes can cause a premature end-of-file to be indicated. Instead, discover the 'EOF push as first read character' condition from the read() thread itself, and restart the i/o loop if detected. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Avoid false-sharing echo buffer indicesPeter Hurley
Separate the head & commit indices from the tail index to avoid cache-line contention (so called 'false-sharing') between concurrent threads. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Eliminate counter in __process_echoesPeter Hurley
Since neither echo_commit nor echo_tail can change for the duration of __process_echoes loop, substitute index comparison for the snapshot counter. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Only flush echo output if actually outputPeter Hurley
Don't have the driver flush received echoes if no echoes were actually output. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Process echoes in blocksPeter Hurley
Byte-by-byte echo output is painfully slow, requiring a lock/unlock cycle for every input byte. Instead, perform the echo output in blocks of 256 characters, and at least once per flip buffer receive. Enough space is reserved in the echo buffer to guarantee a full block can be saved without overrunning the echo output. Overrun is prevented by discarding the oldest echoes until enough space exists in the echo buffer to receive at least a full block of new echoes. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Eliminate echo_commit memory barrierPeter Hurley
Use output_lock mutex as a memory barrier when storing echo_commit. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Remove echo_lockPeter Hurley
Adding data to echo_buf (via add_echo_byte()) is guaranteed to be single-threaded, since all callers are from the n_tty_receive_buf() path. Processing the echo_buf can be called from either the n_tty_receive_buf() path or the n_tty_write() path; however, these callers are already serialized by output_lock. Publish cumulative echo_head changes to echo_commit; process echo_buf from echo_tail to echo_commit; remove echo_lock. On echo_buf overrun, claim output_lock to serialize changes to echo_tail. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Replace echo_cnt with computed valuePeter Hurley
Prepare for lockless echo_buf handling; compute current byte count of echo_buf from head and tail indices. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Use separate head and tail indices for echo_bufPeter Hurley
Instead of using a single index to track the current echo_buf position, use a head index when adding to the buffer and a tail index when consuming from the buffer. Allow these head and tail indices to wrap at max representable value; perform modulo reduction via helper functions when accessing the buffer. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Remove unused echo_overrun fieldPeter Hurley
The echo_overrun field is only assigned and never tested; remove it. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Queue buffer work on any available cpuPeter Hurley
Scheduling buffer work on the same cpu as the read() thread limits the parallelism now possible between the receive_buf path and the n_tty_read() path. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Special case pty flow controlPeter Hurley
The pty driver forces ldisc flow control on, regardless of available receive buffer space, so the writer can be woken whenever unthrottle is called. However, this 'forced throttle' has performance consequences, as multiple atomic operations are necessary to unthrottle and perform the write wakeup for every input line (in canonical mode). Instead, short-circuit the unthrottle if the tty is a pty and perform the write wakeup directly. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Move n_tty_write_wakeup() to avoid forward declarationPeter Hurley
Prepare to special case pty flow control; avoid forward declaration. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Factor throttle/unthrottle into helper functionsPeter Hurley
Prepare for special handling of pty throttle/unthrottle; factor flow control into helper functions. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Move chars_in_buffer() to factor throttle/unthrottlePeter Hurley
Prepare to factor throttle and unthrottle into helper functions; relocate chars_in_buffer() to avoid forward declaration. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23tty: Only guarantee termios read safety for throttle/unthrottlePeter Hurley
No tty driver modifies termios during throttle() or unthrottle(). Therefore, only read safety is required. However, tty_throttle_safe and tty_unthrottle_safe must still be mutually exclusive; introduce throttle_mutex for that purpose. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Separate buffer indices to prevent cache-line sharingPeter Hurley
If the read buffer indices are in the same cache-line, cpus will contended over the cache-line (so called 'false sharing'). Separate the producer-published fields from the consumer-published fields; document the locks relevant to each field. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Don't wait for buffer work in read() loopPeter Hurley
User-space read() can run concurrently with receiving from device; waiting for receive_buf() to complete is not required. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Fix type mismatches in receive_buf raw copyPeter Hurley
Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Reset lnext if canonical mode changesPeter Hurley
lnext escapes the next input character as a literal, and must be reset when canonical mode changes (to avoid misinterpreting a special character as a literal if canonical mode is changed back again). lnext is specifically not reset on a buffer flush so as to avoid misinterpreting the next input character as a special character. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Make N_TTY ldisc receive path locklessPeter Hurley
n_tty has a single-producer/single-consumer input model; use lockless publish instead. Use termios_rwsem to exclude both consumer and producer while changing or resetting buffer indices, eg., when flushing. Also, claim exclusive termios_rwsem to safely retrieve the buffer indices from a thread other than consumer or producer (eg., TIOCINQ ioctl). Note the read_tail is published _after_ clearing the newline indicator in read_flags to avoid racing the producer. Drop read_lock spinlock. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Replace canon_data with index comparisonPeter Hurley
canon_data represented the # of lines which had been copied to the receive buffer but not yet copied to the user buffer. The value was tested to determine if input was available in canonical mode (and also to force input overrun if the receive buffer was full but a newline had not been received). However, the actual count was irrelevent; only whether it was non-zero (meaning 'is there any input to transfer?'). This shared count is unnecessary and unsafe with a lockless algorithm. The same check is made by comparing canon_head with read_tail instead. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Access termios values safelyPeter Hurley
Use termios_rwsem to guarantee safe access to the termios values. This is particularly important for N_TTY as changing certain termios settings alters the mode of operation. termios_rwsem must be dropped across throttle/unthrottle since those functions claim the termios_rwsem exclusively (to guarantee safe access to the termios and for mutual exclusion). Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23tty: Convert termios_mutex to termios_rwsemPeter Hurley
termios is commonly accessed unsafely (especially by N_TTY) because the existing mutex forces exclusive access. Convert existing usage. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Remove read_cntPeter Hurley
Storing the read_cnt creates an unnecessary shared variable between the single-producer (n_tty_receive_buf()) and the single-consumer (n_tty_read()). Compute read_cnt from head & tail instead of storing. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Don't wrap input buffer indices at buffer sizePeter Hurley
Wrap read_buf indices (read_head, read_tail, canon_head) at max representable value, instead of at the N_TTY_BUF_SIZE. This step is necessary to allow lockless reads of these shared variables (by updating the variables atomically). Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Get read_cnt through accessorPeter Hurley
Prepare for replacing read_cnt field with computed value. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23tty: Deprecate ldisc .chars_in_buffer() methodPeter Hurley
Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Split n_tty_chars_in_buffer() for reader-only interfacePeter Hurley
N_TTY .chars_in_buffer() method requires serialized access if the current thread is not the single-consumer, n_tty_read(). Separate the internal interface; prepare for lockless read-side. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Line copy to user buffer in canonical modePeter Hurley
Instead of pushing one char per loop, pre-compute the data length to copy and copy all at once. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23n_tty: Factor canonical mode copy from n_tty_read()Peter Hurley
Simplify n_tty_read(); extract complex copy algorithm into separate function, canon_copy_to_user(). Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-07-23tty: Make ldisc input flow control concurrency-friendlyPeter Hurley
Although line discipline receiving is single-producer/single-consumer, using tty->receive_room to manage flow control creates unnecessary critical regions requiring additional lock use. Instead, introduce the optional .receive_buf2() ldisc method which returns the # of bytes actually received. Serialization is guaranteed by the caller. In turn, the line discipline should schedule the buffer work item whenever space becomes available; ie., when there is room to receive data and receive_room() previously returned 0 (the buffer work item stops processing if receive_buf2() returns 0). Note the 'no room' state need not be atomic despite concurrent use by two threads because only the buffer work thread can set the state and only the read() thread can clear the state. Add n_tty_receive_buf2() as the receive_buf2() method for N_TTY. Provide a public helper function, tty_ldisc_receive_buf(), to use when directly accessing the receive_buf() methods. Line disciplines not using input flow control can continue to set tty->receive_room to a fixed value and only provide the receive_buf() method. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-06-17n_tty: Buffer work should not reschedule itselfPeter Hurley
Although the driver-side input path must update the available buffer space, it should not reschedule itself. If space is still available and the flip buffers are not empty, flush_to_ldisc() will loop again. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-06-17n_tty: Fix unsafe update of available buffer spacePeter Hurley
receive_room is used to control the amount of data the flip buffer work can push to the read buffer. This update is unsafe: CPU 0 | CPU 1 | | n_tty_read() | n_tty_set_room() | left = <calc of space> n_tty_receive_buf() | <push data to buffer> | n_tty_set_room() | left = <calc of space> | tty->receive_room = left | | tty->receive_room = left receive_room is now updated with a stale calculation of the available buffer space, and the subsequent work loop will likely overwrite unread data in the input buffer. Update receive_room atomically with the calculation of the available buffer space. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-06-17n_tty: Untangle read completion variablesPeter Hurley
Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-06-17n_tty: Encapsulate minimum_to_wake within N_TTYPeter Hurley
minimum_to_wake is unique to N_TTY processing, and belongs in per-ldisc data. Add the ldisc method, ldisc_ops::fasync(), to notify line disciplines when signal-driven I/O is enabled or disabled. When enabled for N_TTY (by fcntl(F_SETFL, O_ASYNC)), blocking reader/polls will be woken for any readable input. When disabled, blocking reader/polls are not woken until the read buffer is full. Canonical mode (L_ICANON(tty), n_tty_data::icanon) is not affected by the minimum_to_wake setting. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-05-27Merge 3.10-rc3 into tty-nextGreg Kroah-Hartman
We want these fixes. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-05-20TTY: Fix tty miss restart after we turn off flow-controlWang YanQing
I meet emacs hang in start if I do the operation below: 1: echo 3 > /proc/sys/vm/drop_caches 2: emacs BigFile 3: Press CTRL-S follow 2 immediately Then emacs hang on, CTRL-Q can't resume, the terminal hang on, you can do nothing with this terminal except close it. The reason is before emacs takeover control the tty, we use CTRL-S to XOFF it. Then when emacs takeover the control, it may don't use the flow-control, so emacs hang. This patch fix it. This patch will fix a kind of strange tty relation hang problem, I believe I meet it with vim in ssh, and also see below bug report: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=465823 Signed-off-by: Wang YanQing <udknight@gmail.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-05-20tty: Remove TTY_HW_COOK_IN/OUTPeter Hurley
No in-tree tty driver supports cooked mode in hardware; remove. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-03-18n_tty: Fully initialize ldisc before restarting buffer workPeter Hurley
Buffer work may already be pending when the n_tty ldisc is re-opened, eg., when setting the ldisc (via TIOCSETD ioctl) and when hanging up the tty. Since n_tty_set_room() may restart buffer work, first ensure the ldisc is completely initialized. Factor n_tty_set_room() out of reset_buffer_flags() (only 2 callers) and reorganize n_tty_open() to set termios last; buffer work will be restarted there if necessary, after the char_map is properly initialized. Fixes this WARNING: [ 549.561769] ------------[ cut here ]------------ [ 549.598755] WARNING: at drivers/tty/n_tty.c:160 n_tty_set_room+0xff/0x130() [ 549.604058] scheduling buffer work for halted ldisc [ 549.607741] Pid: 9417, comm: trinity-child28 Tainted: G D W 3.7.0-next-20121217-sasha-00023-g8689ef9 #219 [ 549.652580] Call Trace: [ 549.662754] [<ffffffff81c432cf>] ? n_tty_set_room+0xff/0x130 [ 549.665458] [<ffffffff8110cae7>] warn_slowpath_common+0x87/0xb0 [ 549.668257] [<ffffffff8110cb71>] warn_slowpath_fmt+0x41/0x50 [ 549.671007] [<ffffffff81c432cf>] n_tty_set_room+0xff/0x130 [ 549.673268] [<ffffffff81c44597>] reset_buffer_flags+0x137/0x150 [ 549.675607] [<ffffffff81c45b71>] n_tty_open+0x131/0x1c0 [ 549.677699] [<ffffffff81c47824>] tty_ldisc_open.isra.5+0x54/0x70 [ 549.680147] [<ffffffff81c482bf>] tty_ldisc_hangup+0x11f/0x1e0 [ 549.682409] [<ffffffff81c3fa17>] __tty_hangup+0x137/0x440 [ 549.684634] [<ffffffff81c3fd49>] tty_vhangup+0x9/0x10 [ 549.686443] [<ffffffff81c4a42c>] pty_close+0x14c/0x160 [ 549.688446] [<ffffffff81c41225>] tty_release+0xd5/0x490 [ 549.690460] [<ffffffff8127d8a2>] __fput+0x122/0x250 [ 549.692577] [<ffffffff8127d9d9>] ____fput+0x9/0x10 [ 549.694534] [<ffffffff811348c2>] task_work_run+0xb2/0xf0 [ 549.696349] [<ffffffff81113c6d>] do_exit+0x36d/0x580 [ 549.698286] [<ffffffff8107d964>] ? syscall_trace_enter+0x24/0x2e0 [ 549.702729] [<ffffffff81113f4a>] do_group_exit+0x8a/0xc0 [ 549.706775] [<ffffffff81113f92>] sys_exit_group+0x12/0x20 [ 549.711088] [<ffffffff83cfab18>] tracesys+0xe1/0xe6 [ 549.728001] ---[ end trace 73eb41728f11f87e ]--- Reported-by: Sasha Levin <levinsasha928@gmail.com> Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-03-18n_tty: Correct unthrottle-with-buffer-flush commentsPeter Hurley
The driver is no longer unthrottled on buffer reset, so remove comments that claim it is. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-03-18n_tty: Don't flush buffer when closing ldiscPeter Hurley
A buffer flush is both undesirable and unnecessary when the ldisc is closing. A buffer flush performs the following: 1. resets ldisc data fields to their initial state 2. resets tty->receive_room to indicate more data can be sent 3. schedules buffer work to receive more data 4. signals a buffer flush has happened to linked pty in packet mode Since the ldisc has been halted and the tty may soon be destructed, buffer work must not be scheduled as that work might access an invalid tty and ldisc state. Also, the ldisc read buffer is about to be freed, so that's pointless. Resetting the ldisc data fields is pointless as well since that structure is about to be freed. Resetting tty->receive_room is unnecessary, as it will be properly reset if a new ldisc is reopened. Besides, resetting the original receive_room value would be wrong since the read buffer will be gone. Since the packet mode flush is observable from userspace, this behavior has been preserved. The test jig originally authored by Ilya Zykov <ilya@ilyx.ru> and signed off by him is included below. The test jig prompts the following warnings which this patch fixes. [ 38.051111] ------------[ cut here ]------------ [ 38.052113] WARNING: at drivers/tty/n_tty.c:160 n_tty_set_room.part.6+0x8b/0xa0() [ 38.053916] Hardware name: Bochs [ 38.054819] Modules linked in: netconsole configfs bnep rfcomm bluetooth parport_pc ppdev snd_hda_intel snd_hda_codec snd_hwdep snd_pcm snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq psmouse snd_timer serio_raw mac_hid snd_seq_device snd microcode lp parport virtio_balloon soundcore i2c_piix4 snd_page_alloc floppy 8139too 8139cp [ 38.059704] Pid: 1564, comm: pty_kill Tainted: G W 3.7.0-next-20121130+ttydebug-xeon #20121130+ttydebug [ 38.061578] Call Trace: [ 38.062491] [<ffffffff81058b4f>] warn_slowpath_common+0x7f/0xc0 [ 38.063448] [<ffffffff81058baa>] warn_slowpath_null+0x1a/0x20 [ 38.064439] [<ffffffff8142dc2b>] n_tty_set_room.part.6+0x8b/0xa0 [ 38.065381] [<ffffffff8142dc82>] n_tty_set_room+0x42/0x80 [ 38.066323] [<ffffffff8142e6f2>] reset_buffer_flags+0x102/0x160 [ 38.077508] [<ffffffff8142e76d>] n_tty_flush_buffer+0x1d/0x90 [ 38.078782] [<ffffffff81046569>] ? default_spin_lock_flags+0x9/0x10 [ 38.079734] [<ffffffff8142e804>] n_tty_close+0x24/0x60 [ 38.080730] [<ffffffff81431b61>] tty_ldisc_close.isra.2+0x41/0x60 [ 38.081680] [<ffffffff81431bbb>] tty_ldisc_kill+0x3b/0x80 [ 38.082618] [<ffffffff81432a07>] tty_ldisc_release+0x77/0xe0 [ 38.083549] [<ffffffff8142b781>] tty_release+0x451/0x4d0 [ 38.084525] [<ffffffff811950be>] __fput+0xae/0x230 [ 38.085472] [<ffffffff8119524e>] ____fput+0xe/0x10 [ 38.086401] [<ffffffff8107aa88>] task_work_run+0xc8/0xf0 [ 38.087334] [<ffffffff8105ea56>] do_exit+0x196/0x4b0 [ 38.088304] [<ffffffff8106c77b>] ? __dequeue_signal+0x6b/0xb0 [ 38.089240] [<ffffffff8105ef34>] do_group_exit+0x44/0xa0 [ 38.090182] [<ffffffff8106f43d>] get_signal_to_deliver+0x20d/0x4e0 [ 38.091125] [<ffffffff81016979>] do_signal+0x29/0x130 [ 38.092096] [<ffffffff81431a9e>] ? tty_ldisc_deref+0xe/0x10 [ 38.093030] [<ffffffff8142a317>] ? tty_write+0xb7/0xf0 [ 38.093976] [<ffffffff81193f53>] ? vfs_write+0xb3/0x180 [ 38.094904] [<ffffffff81016b20>] do_notify_resume+0x80/0xc0 [ 38.095830] [<ffffffff81700492>] int_signal+0x12/0x17 [ 38.096788] ---[ end trace 5f6f7a9651cd999b ]--- [ 2730.570602] ------------[ cut here ]------------ [ 2730.572130] WARNING: at drivers/tty/n_tty.c:160 n_tty_set_room+0x107/0x140() [ 2730.574904] scheduling buffer work for halted ldisc [ 2730.578303] Pid: 9691, comm: trinity-child15 Tainted: G W 3.7.0-rc8-next-20121205-sasha-00023-g59f0d85 #207 [ 2730.588694] Call Trace: [ 2730.590486] [<ffffffff81c41d77>] ? n_tty_set_room+0x107/0x140 [ 2730.592559] [<ffffffff8110c827>] warn_slowpath_common+0x87/0xb0 [ 2730.595317] [<ffffffff8110c8b1>] warn_slowpath_fmt+0x41/0x50 [ 2730.599186] [<ffffffff81c41d77>] n_tty_set_room+0x107/0x140 [ 2730.603141] [<ffffffff81c42fe7>] reset_buffer_flags+0x137/0x150 [ 2730.607166] [<ffffffff81c43018>] n_tty_flush_buffer+0x18/0x90 [ 2730.610123] [<ffffffff81c430af>] n_tty_close+0x1f/0x60 [ 2730.612068] [<ffffffff81c461f2>] tty_ldisc_close.isra.4+0x52/0x60 [ 2730.614078] [<ffffffff81c462ab>] tty_ldisc_reinit+0x3b/0x70 [ 2730.615891] [<ffffffff81c46db2>] tty_ldisc_hangup+0x102/0x1e0 [ 2730.617780] [<ffffffff81c3e537>] __tty_hangup+0x137/0x440 [ 2730.619547] [<ffffffff81c3e869>] tty_vhangup+0x9/0x10 [ 2730.621266] [<ffffffff81c48f1c>] pty_close+0x14c/0x160 [ 2730.622952] [<ffffffff81c3fd45>] tty_release+0xd5/0x490 [ 2730.624674] [<ffffffff8127fbe2>] __fput+0x122/0x250 [ 2730.626195] [<ffffffff8127fd19>] ____fput+0x9/0x10 [ 2730.627758] [<ffffffff81134602>] task_work_run+0xb2/0xf0 [ 2730.629491] [<ffffffff811139ad>] do_exit+0x36d/0x580 [ 2730.631159] [<ffffffff81113c8a>] do_group_exit+0x8a/0xc0 [ 2730.632819] [<ffffffff81127351>] get_signal_to_deliver+0x501/0x5b0 [ 2730.634758] [<ffffffff8106de34>] do_signal+0x24/0x100 [ 2730.636412] [<ffffffff81204865>] ? user_exit+0xa5/0xd0 [ 2730.638078] [<ffffffff81183cd8>] ? trace_hardirqs_on_caller+0x118/0x140 [ 2730.640279] [<ffffffff81183d0d>] ? trace_hardirqs_on+0xd/0x10 [ 2730.642164] [<ffffffff8106df78>] do_notify_resume+0x48/0xa0 [ 2730.643966] [<ffffffff83cdff6a>] int_signal+0x12/0x17 [ 2730.645672] ---[ end trace a40d53149c07fce0 ]--- /* * pty_thrash.c * * Based on original test jig by Ilya Zykov <ilya@ilyx.ru> * * Signed-off-by: Peter Hurley <peter@hurleysoftware.com> * Signed-off-by: Ilya Zykov <ilya@ilyx.ru> */ static int fd; static void error_exit(char *f, ...) { va_list va; va_start(va, f); vprintf(f, va); printf(": %s\n", strerror(errno)); va_end(va); if (fd >= 0) close(fd); exit(EXIT_FAILURE); } int main(int argc, char *argv[]) { int parent; char pts_name[24]; int ptn, unlock; while (1) { fd = open("/dev/ptmx", O_RDWR); if (fd < 0) error_exit("opening pty master"); unlock = 0; if (ioctl(fd, TIOCSPTLCK, &unlock) < 0) error_exit("unlocking pty pair"); if (ioctl(fd, TIOCGPTN, &ptn) < 0) error_exit("getting pty #"); snprintf(pts_name, sizeof(pts_name), "/dev/pts/%d", ptn); child_id = fork(); if (child_id == -1) error_exit("forking child"); if (parent) { int err, id, status; char buf[128]; int n; n = read(fd, buf, sizeof(buf)); if (n < 0) error_exit("master reading"); printf("%.*s\n", n-1, buf); close(fd); err = kill(child_id, SIGKILL); if (err < 0) error_exit("killing child"); id = waitpid(child_id, &status, 0); if (id < 0 || id != child_id) error_exit("waiting for child"); } else { /* Child */ close(fd); printf("Test cycle on slave pty %s\n", pts_name); fd = open(pts_name, O_RDWR); if (fd < 0) error_exit("opening pty slave"); while (1) { char pattern[] = "test\n"; if (write(fd, pattern, strlen(pattern)) < 0) error_exit("slave writing"); } } } /* never gets here */ return 0; } Reported-by: Sasha Levin <levinsasha928@gmail.com> Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-03-18n_tty: Factor packet mode status change for reusePeter Hurley
Factor the packet mode status change from n_tty_flush_buffer for use by follow-on patch. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-03-18tty: Add diagnostic for halted line disciplinePeter Hurley
Flip buffer work must not be scheduled by the line discipline after the line discipline has been halted; issue warning. Note: drivers can still schedule flip buffer work. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-03-18n_tty: Lock access to tty->pgrp for POSIX job controlPeter Hurley
Concurrent access to tty->pgrp must be protected with tty->ctrl_lock. Also, as noted in the comments, reading current->signal->tty is safe because either, 1) current->signal->tty is assigned by current, or 2) current->signal->tty is set to NULL. NB: for reference, tty_check_change() implements a similar POSIX check for the ioctls corresponding to tcflush(), tcdrain(), tcsetattr(), tcsetpgrp(), tcflow() and tcsendbreak(). Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-03-18n_tty: Fix unsafe driver-side signalsPeter Hurley
An ldisc reference is insufficient guarantee the foreground process group is not in the process of being signalled from a hangup. 1) Reads of tty->pgrp must be locked with ctrl_lock 2) The group pid must be referenced for the duration of signalling. Because the driver-side is not process-context, a pid reference must be acquired. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-03-18n_tty: Fix stuck throttled driverPeter Hurley
As noted in the following comment: /* FIXME: there is a tiny race here if the receive room check runs before the other work executes and empties the buffer (upping the receiving room and unthrottling. We then throttle and get stuck. This has been observed and traced down by Vincent Pillet/ We need to address this when we sort out out the rx path locking */ Use new safe throttle/unthrottle functions to re-evaluate conditions if interrupted by the complement flow control function. Reported-by: Vincent Pillet <vincentx.pillet@intel.com> Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2013-03-18n_tty: Inline check_unthrottle() at lone call sitePeter Hurley
2-line function check_unthrottle() is now only called from n_tty_read(); merge into caller. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>