1. 23 10月, 2012 3 次提交
  2. 10 4月, 2012 1 次提交
  3. 08 6月, 2011 1 次提交
    • L
      tty_buffer: get rid of 'seen_tail' logic in flush_to_ldisc · 81de916f
      Linus Torvalds 提交于
      The flush_to_ldisc() work entry has special logic to notice when it has
      seen the original tail of the data queue, and it avoids continuing the
      flush if it sees that _original_ tail rather than the current tail.
      
      This logic can trigger in case somebody is constantly adding new data to
      the tty while the flushing is active - and the intent is to avoid
      excessive CPU usage while flushing the tty, especially as we used to do
      this from a softirq context which made it non-preemptible.
      
      However, since we no longer re-arm the work-queue from within itself
      (because that causes other trouble: see commit a5660b41 "tty: fix
      endless work loop when the buffer fills up"), this just leads to
      possible hung tty's (most easily seen in SMP and with a test-program
      that floods a pty with data - nobody seems to have reported this for any
      real-life situation yet).
      
      And since the workqueue isn't done from timers and softirq's any more,
      it's doubtful whether the CPU useage issue is really relevant any more.
      So just remove the logic entirely, and see if anybody ever notices.
      
      Alternatively, we might want to re-introduce the "re-arm the work" for
      just this case, but then we'd have to re-introduce the delayed work
      model or some explicit timer, which really doesn't seem worth it for
      this.
      Reported-and-tested-by: NGuillaume Chazarain <guichaz@gmail.com>
      Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
      Cc: Felipe Balbi <balbi@ti.com>
      Cc: Greg Kroah-Hartman <gregkh@suse.de>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      81de916f
  4. 04 6月, 2011 1 次提交
    • L
      Revert "tty: make receive_buf() return the amout of bytes received" · 55db4c64
      Linus Torvalds 提交于
      This reverts commit b1c43f82.
      
      It was broken in so many ways, and results in random odd pty issues.
      
      It re-introduced the buggy schedule_work() in flush_to_ldisc() that can
      cause endless work-loops (see commit a5660b41: "tty: fix endless
      work loop when the buffer fills up").
      
      It also used an "unsigned int" return value fo the ->receive_buf()
      function, but then made multiple functions return a negative error code,
      and didn't actually check for the error in the caller.
      
      And it didn't actually work at all.  BenH bisected down odd tty behavior
      to it:
        "It looks like the patch is causing some major malfunctions of the X
         server for me, possibly related to PTYs.  For example, cat'ing a
         large file in a gnome terminal hangs the kernel for -minutes- in a
         loop of what looks like flush_to_ldisc/workqueue code, (some ftrace
         data in the quoted bits further down).
      
         ...
      
         Some more data: It -looks- like what happens is that the
         flush_to_ldisc work queue entry constantly re-queues itself (because
         the PTY is full ?) and the workqueue thread will basically loop
         forver calling it without ever scheduling, thus starving the consumer
         process that could have emptied the PTY."
      
      which is pretty much exactly the problem we fixed in a5660b41.
      
      Milton Miller pointed out the 'unsigned int' issue.
      Reported-by: NBenjamin Herrenschmidt <benh@kernel.crashing.org>
      Reported-by: NMilton Miller <miltonm@bga.com>
      Cc: Stefan Bigler <stefan.bigler@keymile.com>
      Cc: Toby Gray <toby.gray@realvnc.com>
      Cc: Felipe Balbi <balbi@ti.com>
      Cc: Greg Kroah-Hartman <gregkh@suse.de>
      Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      55db4c64
  5. 23 4月, 2011 1 次提交
  6. 05 4月, 2011 1 次提交
    • L
      tty: fix endless work loop when the buffer fills up · a5660b41
      Linus Torvalds 提交于
      Commit f23eb2b2 ('tty: stop using "delayed_work" in the tty layer')
      ended up causing hung machines on UP with no preemption, because the
      work routine to flip the buffer data to the ldisc would endlessly re-arm
      itself if the destination buffer had filled up.
      
      With the delayed work, that only caused a timer-driving polling of the
      tty state every timer tick, but without the delay we just ended up with
      basically a busy loop instead.
      
      Stop the insane polling, and instead make the code that opens up the
      receive room re-schedule the buffer flip work.  That's what we should
      have been doing anyway.
      
      This same "poll for tty room" issue is almost certainly also the cause
      of excessive kworker activity when idle reported by Dave Jones, who also
      reported "flush_to_ldisc executing 2500 times a second" back in Nov 2010:
      
        http://lkml.org/lkml/2010/11/30/592
      
      which is that silly flushing done every timer tick.  Wasting both power
      and CPU for no good reason.
      Reported-and-tested-by: NAlexander Beregalov <a.beregalov@gmail.com>
      Reported-and-tested-by: NSitsofe Wheeler <sitsofe@yahoo.com>
      Cc: Greg KH <gregkh@suse.de>
      Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
      Cc: Dave Jones <davej@redhat.com>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      a5660b41
  7. 23 3月, 2011 1 次提交
    • L
      tty: stop using "delayed_work" in the tty layer · f23eb2b2
      Linus Torvalds 提交于
      Using delayed-work for tty flip buffers ends up causing us to wait for
      the next tick to complete some actions.  That's usually not all that
      noticeable, but for certain latency-critical workloads it ends up being
      totally unacceptable.
      
      As an extreme case of this, passing a token back-and-forth over a pty
      will take two ticks per iteration, so even just a thousand iterations
      will take 8 seconds assuming a common 250Hz configuration.
      
      Avoiding the whole delayed work issue brings that ping-pong test-case
      down to 0.009s on my machine.
      
      In more practical terms, this latency has been a performance problem for
      things like dive computer simulators (simulating the serial interface
      using the ptys) and for other environments (Alan mentions a CP/M emulator).
      Reported-by: NJef Driesen <jefdriesen@telenet.be>
      Acked-by: NGreg KH <gregkh@suse.de>
      Acked-by: NAlan Cox <alan@lxorguk.ukuu.org.uk>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      f23eb2b2
  8. 10 11月, 2010 1 次提交
    • J
      tty: prevent DOS in the flush_to_ldisc · e045fec4
      Jiri Olsa 提交于
      There's a small window inside the flush_to_ldisc function,
      where the tty is unlocked and calling ldisc's receive_buf
      function. If in this window new buffer is added to the tty,
      the processing might never leave the flush_to_ldisc function.
      
      This scenario will hog the cpu, causing other tty processing
      starving, and making it impossible to interface the computer
      via tty.
      
      I was able to exploit this via pty interface by sending only
      control characters to the master input, causing the flush_to_ldisc
      to be scheduled, but never actually generate any output.
      
      To reproduce, please run multiple instances of following code.
      
      - SNIP
      #define _XOPEN_SOURCE
      #include <stdlib.h>
      #include <stdio.h>
      #include <sys/types.h>
      #include <sys/stat.h>
      #include <fcntl.h>
      
      int main(int argc, char **argv)
      {
              int i, slave, master = getpt();
              char buf[8192];
      
              sprintf(buf, "%s", ptsname(master));
              grantpt(master);
              unlockpt(master);
      
              slave = open(buf, O_RDWR);
              if (slave < 0) {
                      perror("open slave failed");
                      return 1;
              }
      
              for(i = 0; i < sizeof(buf); i++)
                      buf[i] = rand() % 32;
      
              while(1) {
                      write(master, buf, sizeof(buf));
              }
      
              return 0;
      }
      - SNIP
      
      The attached patch (based on -next tree) fixes this by checking on the
      tty buffer tail. Once it's reached, the current work is rescheduled
      and another could run.
      Signed-off-by: NJiri Olsa <jolsa@redhat.com>
      Cc: stable <stable@kernel.org>
      Acked-by: NAlan Cox <alan@lxorguk.ukuu.org.uk>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      e045fec4
  9. 05 11月, 2010 1 次提交
  10. 22 5月, 2010 1 次提交
  11. 19 3月, 2010 1 次提交
    • F
      tty_buffer: Fix distinct type warning · d4bee0a6
      Fang Wenqi 提交于
      CC      drivers/char/tty_buffer.o
      drivers/char/tty_buffer.c: In function ‘tty_insert_flip_string_fixed_flag’:
      drivers/char/tty_buffer.c:251: warning: comparison of distinct pointer types lacks a cast
      drivers/char/tty_buffer.c: In function ‘tty_insert_flip_string_flags’:
      drivers/char/tty_buffer.c:288: warning: comparison of distinct pointer types lacks a cast
      
      Fix it by replacing min() with min_t() in tty_insert_flip_string_flags and
      					  tty_insert_flip_string_fixed_flag().
      Signed-off-by: NFang Wenqi <antonf@turbolinux.com.cn>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      d4bee0a6
  12. 03 3月, 2010 2 次提交
  13. 15 10月, 2009 3 次提交
    • L
      tty: use the new 'flush_delayed_work()' helper to do ldisc flush · 97ad5a03
      Linus Torvalds 提交于
      This way all flush_to_ldisc work is always done through the workqueues,
      and we thus have a single point of serialization.  It also means that we
      can avoid calling flush_to_ldisc() entirely if there was no delayed work
      pending.
      
      [ Side note: using workqueues and keventd as the single way to enter
        flush_to_ldisc() still doesn't absolutely guarantee that we can't have
        concurrency: keventd is multithreaded and has a thread per CPU, and
        while the WORK_STRUCT_PENDING bit guarantees a single work only being
        on the pending list once, the work might be both pending and _running_
        at the same time. Workqueues are not simple. ]
      
      This was also confirmed to fix bugzilla #14388, even without the earlier
      locking fix and cleanup (commit c8e33141: "tty: Make flush_to_ldisc()
      locking more robust").  So both commits fix the same bug differently,
      and either would have worked on its own.  But I'm committing them both
      since they are cleanups independent of each other.
      Reported-and-tested-by: NBoyan <btanastasov@yahoo.co.uk>
      Acked-by: NAlan Cox <alan@lxorguk.ukuu.org.uk>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      97ad5a03
    • L
      tty: Make flush_to_ldisc() locking more robust · c8e33141
      Linus Torvalds 提交于
      The locking logic in this function is extremely subtle, and it broke
      when we started doing potentially concurrent 'flush_to_ldisc()' calls in
      commit e043e42b ("pty: avoid forcing
      'low_latency' tty flag").
      
      The code in flush_to_ldisc() used to set 'tty->buf.head' to NULL, with
      the intention that this would then cause any other concurrent calls to
      not do anything (locking note: we have to drop the buf.lock over the
      call to ->receive_buf that can block, which is why we can have
      concurrency here at all in the first place).
      
      It also used to set the TTY_FLUSHING bit, which would then cause any
      concurrent 'tty_buffer_flush()' to not free all the tty buffers and
      clear 'tty->buf.tail'.  And with 'buf.head' being NULL, and 'buf.tail'
      being non-NULL, new data would never touch 'buf.head'.
      
      Does that sound a bit too subtle? It was.  If another concurrent call to
      'flush_to_ldisc()' were to come in, the NULL buf.head would indeed cause
      it to not process the buffer list, but it would still clear TTY_FLUSHING
      afterwards, making the buffer protection against 'tty_buffer_flush()' no
      longer work.
      
      So this clears it all up.  We depend purely on TTY_FLUSHING for handling
      re-entrancy, and stop playing games with the buffer list entirely.  In
      fact, the buffer list handling is now robust enough that we could
      probably stop doing the whole "protect against 'tty_buffer_flush()'"
      thing entirely.
      
      However, Alan also points out that we would probably be better off
      simplifying the locking even further, and just take the tty ldisc_mutex
      around all the buffer flushing calls.  That seems like a good idea, but
      in the meantime this is a conceptually minimal fix (with the patch
      itself being bigger than required just to clean the code up and make it
      readable).
      
      This fixes keyboard trouble under X:
      
      	http://bugzilla.kernel.org/show_bug.cgi?id=14388Reported-and-tested-by: NFrédéric Meunier <fredlwm@gmail.com>
      Reported-and-tested-by: NBoyan <btanastasov@yahoo.co.uk>
      Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
      Cc: Paul Fulghum <paulkf@microgate.com>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      c8e33141
    • L
      tty: use the new 'flush_delayed_work()' helper to do ldisc flush · 514fc01d
      Linus Torvalds 提交于
      This way all flush_to_ldisc work is always done through the workqueues,
      and we thus have a single point of serialization.
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      514fc01d
  14. 14 10月, 2009 1 次提交
  15. 30 7月, 2009 1 次提交
    • O
      pty: avoid forcing 'low_latency' tty flag · e043e42b
      OGAWA Hirofumi 提交于
      We really don't want to mark the pty as a low-latency device, because as
      Alan points out, the ->write method can be called from an IRQ (ppp?),
      and that means we can't use ->low_latency=1 as we take mutexes in the
      low_latency case.
      
      So rather than using low_latency to force the written data to be pushed
      to the ldisc handling at 'write()' time, just make the reader side (or
      the poll function) do the flush when it checks whether there is data to
      be had.
      
      This also fixes the problem with lost data in an emacs compile buffer
      (bugzilla 13815), and we can thus revert the low_latency pty hack
      (commit 3a542974: "pty: quickfix for the
      pty ENXIO timing problems").
      Signed-off-by: NOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
      Tested-by: NAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
      [ Modified to do the tty_flush_to_ldisc() inside input_available_p() so
        that it triggers for both read and poll()  - Linus]
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      e043e42b
  16. 14 10月, 2008 1 次提交