1. 08 6月, 2011 1 次提交
    • J
      TTY: ldisc, do not close until there are readers · 92f6fa09
      Jiri Slaby 提交于
      We restored tty_ldisc_wait_idle in 100eeae2 (TTY: restore
      tty_ldisc_wait_idle). We used it in the ldisc changing path to fix the
      case where there are tasks in n_tty_read waiting for data and somebody
      tries to change ldisc.
      
      Similar to the case above, there may be also tasks waiting in
      n_tty_read while hangup is performed. As 65b77046 (tty-ldisc: turn
      ldisc user count into a proper refcount) removed the wait-until-idle
      from all paths, hangup path won't wait for them to disappear either
      now. So add it back even to the hangup path.
      
      There is a difference, we need uninterruptible sleep as there is
      obviously HUP signal pending. So tty_ldisc_wait_idle now sleeps
      without possibility to be interrupted. This is what original
      tty_ldisc_wait_idle did. After the wait idle reintroduction
      (100eeae2), we have had interruptible sleeps for the ldisc changing
      path. But as there is a 5s timeout anyway, we don't allow it to be
      interrupted from now on. It's not worth the added complexity of
      deciding what kind of sleep we want.
      
      Before 65b77046 tty_ldisc_release was called also from
      tty_ldisc_release. It is called from tty_release, so I don't think we
      need to restore that one.
      
      This is nicely reproducible after constifying the timing when
      drivers/tty/n_tty.c is patched as follows ("TTY: ntty, add one more
      sanity check" patch is needed to actually see it explode):
      %% -1548,6 +1549,7 @@ static int n_tty_open(struct tty_struct *tty)
      
              /* These are ugly. Currently a malloc failure here can panic */
              if (!tty->read_buf) {
      +               msleep(100);
                      tty->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL);
                      if (!tty->read_buf)
                              return -ENOMEM;
      %% -1785,6 +1788,7 @@ do_it_again:
                                      break;
                              }
                              timeout = schedule_timeout(timeout);
      +                       msleep(20);
                              continue;
                      }
                      __set_current_state(TASK_RUNNING);
      ===== With a process: =====
          while (1) {
              int fd = open(argv[1], O_RDWR);
              read(fd, buf, sizeof(buf));
              close(fd);
          }
      ===== and its child: =====
              setsid();
              while (1) {
                      int fd = open(tty, O_RDWR|O_NOCTTY);
                      ioctl(fd, TIOCSCTTY, 1);
                      vhangup();
                      close(fd);
                      usleep(100 * (10 + random() % 1000));
              }
      ===== EOF =====
      
      References: https://bugzilla.novell.com/show_bug.cgi?id=693374
      References: https://bugzilla.novell.com/show_bug.cgi?id=694509Signed-off-by: NJiri Slaby <jslaby@suse.cz>
      Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: stable <stable@kernel.org> [32, 33, 34, 39]
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      92f6fa09
  2. 20 4月, 2011 1 次提交
  3. 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
  4. 02 3月, 2011 1 次提交
  5. 04 2月, 2011 1 次提交
  6. 30 11月, 2010 1 次提交
    • J
      TTY: ldisc, fix open flag handling · 7f90cfc5
      Jiri Slaby 提交于
      When a concrete ldisc open fails in tty_ldisc_open, we forget to clear
      TTY_LDISC_OPEN. This causes a false warning on the next ldisc open:
      WARNING: at drivers/char/tty_ldisc.c:445 tty_ldisc_open+0x26/0x38()
      Hardware name: System Product Name
      Modules linked in: ...
      Pid: 5251, comm: a.out Tainted: G        W  2.6.32-5-686 #1
      Call Trace:
       [<c1030321>] ? warn_slowpath_common+0x5e/0x8a
       [<c1030357>] ? warn_slowpath_null+0xa/0xc
       [<c119311c>] ? tty_ldisc_open+0x26/0x38
       [<c11936c5>] ? tty_set_ldisc+0x218/0x304
      ...
      
      So clear the bit when failing...
      
      Introduced in c65c9bc3 (tty: rewrite the ldisc locking) back in
      2.6.31-rc1.
      Signed-off-by: NJiri Slaby <jslaby@suse.cz>
      Cc: Alan Cox <alan@linux.intel.com>
      Reported-by: NSergey Lapin <slapin@ossfans.org>
      Tested-by: NSergey Lapin <slapin@ossfans.org>
      Cc: stable <stable@kernel.org>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      7f90cfc5
  7. 10 11月, 2010 2 次提交
    • P
      tty_ldisc: Fix BUG() on hangup · 1c95ba1e
      Philippe Rétornaz 提交于
      A kernel BUG when bluetooth rfcomm connection drop while the associated
      serial port is open is sometime triggered.
      
      It seems that the line discipline can disappear between the
      tty_ldisc_put and tty_ldisc_get. This patch fall back to the N_TTY line
      discipline if the previous discipline is not available anymore.
      Signed-off-by: NPhilippe Retornaz <philippe.retornaz@epfl.ch>
      Acked-by: NAlan Cox <alan@linux.intel.com>
      Cc: stable <stable@kernel.org>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      1c95ba1e
    • J
      TTY: restore tty_ldisc_wait_idle · 100eeae2
      Jiri Slaby 提交于
      It was removed in 65b77046 (tty-ldisc: turn ldisc user count into
      a proper refcount), but we need to wait for last user to quit the
      ldisc before we close it in tty_set_ldisc.
      
      Otherwise weird things start to happen. There might be processes
      waiting in tty_read->n_tty_read on tty->read_wait for input to appear
      and at that moment, a change of ldisc is fatal. n_tty_close is called,
      it frees read_buf and the waiting process is still in the middle of
      reading and goes nuts after it is woken.
      
      Previously we prevented close to happen when others are in ldisc ops
      by tty_ldisc_wait_idle in tty_set_ldisc. But the commit above removed
      that. So revoke the change and test whether there is 1 user (=we), and
      allow the close then.
      
      We can do that without ldisc/tty locks, because nobody else can open
      the device due to TTY_LDISC_CHANGING bit set, so we in fact wait for
      everybody to leave.
      
      I don't understand why tty_ldisc_lock would be needed either when the
      counter is an atomic variable, so this is a lockless
      tty_ldisc_wait_idle.
      
      On the other hand, if we fail to wait (timeout or signal), we have to
      reenable the halted ldiscs, so we take ldisc lock and reuse the setup
      path at the end of tty_set_ldisc.
      Signed-off-by: NJiri Slaby <jslaby@suse.cz>
      Acked-by: NLinus Torvalds <torvalds@linux-foundation.org>
      Tested-by: NSebastian Andrzej Siewior <bigeasy@breakpoint.cc>
      LKML-Reference: <20101031104136.GA511@Chamillionaire.breakpoint.cc>
      LKML-Reference: <1287669539-22644-1-git-send-email-jslaby@suse.cz>
      Cc: Alan Cox <alan@linux.intel.com>
      Cc: stable@kernel.org [32, 33, 36]
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      100eeae2
  8. 05 11月, 2010 1 次提交
  9. 11 8月, 2010 3 次提交
  10. 03 3月, 2010 1 次提交
    • A
      tty: Fix the ldisc hangup race · 638b9648
      Alan Cox 提交于
      This was noticed by Matthias Urlichs and he proposed a fix. This patch
      does the fixing a different way to avoid introducing several new race
      conditions into the code.
      
      The problem case is TTY_DRIVER_RESET_TERMIOS = 0. In that case while we
      abort the ldisc change, the hangup processing has not cleaned up and restarted
      the ldisc either.
      
      We can't restart the ldisc stuff in the set_ldisc as we don't know what
      the hangup did and may touch stuff we shouldn't as we are no longer
      supposed to influence the tty at that point in case it has been re-opened
      before we get rescheduled.
      
      Instead do it the simple way. Always re-init the ldisc on the hangup, but
      use TTY_DRIVER_RESET_TERMIOS to indicate that we should force N_TTY.
      Signed-off-by: NAlan Cox <alan@linux.intel.com>
      Cc: stable <stable@kernel.org>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      638b9648
  11. 12 12月, 2009 2 次提交
  12. 04 10月, 2009 1 次提交
    • L
      tty: Avoid dropping ldisc_mutex over hangup tty re-initialization · 0b5759c6
      Linus Torvalds 提交于
      A couple of people have hit the WARN_ON() in drivers/char/tty_io.c,
      tty_open() that is unhappy about seeing the tty line discipline go away
      during the tty hangup. See for example
      
      	http://bugzilla.kernel.org/show_bug.cgi?id=14255
      
      and the reason is that we do the tty_ldisc_halt() outside the
      ldisc_mutex in order to be able to flush the scheduled work without a
      deadlock with vhangup_work.
      
      However, it turns out that we can solve this particular case by
      
       - using "cancel_delayed_work_sync()" in tty_ldisc_halt(), which waits
         for just the particular work, rather than synchronizing with any
         random outstanding pending work.
      
         This won't deadlock, since the buf.work we synchronize with doesn't
         care about the ldisc_mutex, it just flushes the tty ldisc buffers.
      
       - realize that for this particular case, we don't need to wait for any
         hangup work, because we are inside the hangup codepaths ourselves.
      
      so as a result we can just drop the flush_scheduled_work() entirely, and
      then move the tty_ldisc_halt() call to inside the mutex.  That way we
      never expose the partially torn down ldisc state to tty_open(), and hold
      the ldisc_mutex over the whole sequence.
      Reported-by: NIngo Molnar <mingo@elte.hu>
      Reported-by: NHeinz Diehl <htd@fancy-poultry.org>
      Cc: stable@kernel.org
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      0b5759c6
  13. 20 9月, 2009 2 次提交
  14. 26 8月, 2009 1 次提交
    • L
      tty: make sure to flush any pending work when halting the ldisc · 5c58ceff
      Linus Torvalds 提交于
      When I rewrote tty ldisc code to use proper reference counts (commits
      65b77046 and cbe9352f) in order to avoid a race with hangup, the
      test-program that Eric Biederman used to trigger the original problem
      seems to have exposed another long-standing bug: the hangup code did the
      'tty_ldisc_halt()' to stop any buffer flushing activity, but unlike the
      other call sites it never actually flushed any pending work.
      
      As a result, if you get just the right timing, the pending work may be
      just about to execute (ie the timer has already triggered and thus
      cancel_delayed_work() was a no-op), when we then re-initialize the ldisc
      from under it.
      
      That, in turn, results in various random problems, usually seen as a
      NULL pointer dereference in run_timer_softirq() or a BUG() in
      worker_thread (but it can be almost anything).
      
      Fix it by adding the required 'flush_scheduled_work()' after doing the
      tty_ldisc_halt() (this also requires us to move the ldisc halt to before
      taking the ldisc mutex in order to avoid a deadlock with the workqueue
      executing do_tty_hangup, which requires the mutex).
      
      The locking should be cleaned up one day (the requirement to do this
      outside the ldisc_mutex is very annoying, and weakens the lock), but
      that's a larger and separate undertaking.
      Reported-by: NEric W. Biederman <ebiederm@xmission.com>
      Tested-by: NXiaotian Feng <xtfeng@gmail.com>
      Tested-by: NYanmin Zhang <yanmin_zhang@linux.intel.com>
      Tested-by: NDave Young <hidave.darkstar@gmail.com>
      Cc: Frederic Weisbecker <fweisbec@gmail.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>
      5c58ceff
  15. 05 8月, 2009 3 次提交
    • L
      tty-ldisc: be more careful in 'put_ldisc' locking · cbe9352f
      Linus Torvalds 提交于
      Use 'atomic_dec_and_lock()' to make sure that we always hold the
      tty_ldisc_lock when the ldisc count goes to zero. That way we can never
      race against 'tty_ldisc_try()' increasing the count again.
      Reported-by: NOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      Tested-by: NSergey Senozhatsky <sergey.senozhatsky@mail.by>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      cbe9352f
    • L
      tty-ldisc: turn ldisc user count into a proper refcount · 65b77046
      Linus Torvalds 提交于
      By using the user count for the actual lifetime rules, we can get rid of
      the silly "wait_for_idle" logic, because any busy ldisc will
      automatically stay around until the last user releases it.  This avoids
      a host of odd issues, and simplifies the code.
      
      So now, when the last ldisc reference is dropped, we just release the
      ldisc operations struct reference, and free the ldisc.
      
      It looks obvious enough, and it does work for me, but the counting
      _could_ be off. It probably isn't (bad counting in the new version would
      generally imply that the old code did something really bad, like free an
      ldisc with a non-zero count), but it does need some testing, and
      preferably somebody looking at it.
      
      With this change, both 'tty_ldisc_put()' and 'tty_ldisc_deref()' are
      just aliases for the new ref-counting 'put_ldisc()'. Both of them
      decrement the ldisc user count and free it if it goes down to zero.
      They're identical functions, in other words.
      
      But the reason they still exist as sepate functions is that one of them
      was exported (tty_ldisc_deref) and had a stupid name (so I don't want to
      use it as the main name), and the other one was used in multiple places
      (and I didn't want to make the patch larger just to rename the users).
      
      In addition to the refcounting, I did do some minimal cleanup. For
      example, now "tty_ldisc_try()" actually returns the ldisc it got under
      the lock, rather than returning true/false and then the caller would
      look up the ldisc again (now without the protection of the lock).
      
      That said, there's tons of dubious use of 'tty->ldisc' without obviously
      proper locking or refcounting left. I expressly did _not_ want to try to
      fix it all, keeping the patch minimal. There may or may not be bugs in
      that kind of code, but they wouldn't be _new_ bugs.
      
      That said, even if the bugs aren't new, the timing and lifetime will
      change. For example, some silly code may depend on the 'tty->ldisc'
      pointer not changing because they hold a refcount on the 'ldisc'. And
      that's no longer true - if you hold a ref on the ldisc, the 'ldisc'
      itself is safe, but tty->ldisc may change.
      
      So the proper locking (remains) to hold tty->ldisc_mutex if you expect
      tty->ldisc to be stable. That's not really a _new_ rule, but it's an
      example of something that the old code might have unintentionally
      depended on and hidden bugs.
      
      Whatever. The patch _looks_ sensible to me. The only users of
      ldisc->users are:
       - get_ldisc() - atomically increment the count
      
       - put_ldisc() - atomically decrements the count and releases if zero
      
       - tty_ldisc_try_get() - creates the ldisc, and sets the count to 1.
         The ldisc should then either be released, or be attached to a tty.
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      Tested-by: NOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
      Tested-by: NSergey Senozhatsky <sergey.senozhatsky@mail.by>
      Acked-by: NAlan Cox <alan@linux.intel.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      65b77046
    • L
      tty-ldisc: make refcount be atomic_t 'users' count · 18eac1cc
      Linus Torvalds 提交于
      This is pure preparation of changing the ldisc reference counting to be
      a true refcount that defines the lifetime of the ldisc.  But this is a
      purely syntactic change for now to make the next steps easier.
      
      This patch should make no semantic changes at all. But I wanted to make
      the ldisc refcount be an atomic (I will be touching it without locks
      soon enough), and I wanted to rename it so that there isn't quite as
      much confusion between 'ldo->refcount' (ldisk operations refcount) and
      'ld->refcount' (ldisc refcount itself) in the same file.
      
      So it's now an atomic 'ld->users' count. It still starts at zero,
      despite having a reference from 'tty->ldisc', but that will change once
      we turn it into a _real_ refcount.
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      Tested-by: NOGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
      Tested-by: NSergey Senozhatsky <sergey.senozhatsky@mail.by>
      Acked-by: NAlan Cox <alan@linux.intel.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@suse.de>
      18eac1cc
  16. 17 7月, 2009 1 次提交
  17. 13 7月, 2009 1 次提交
  18. 30 6月, 2009 1 次提交
    • A
      tty: Fix the leak in tty_ldisc_release · aef29bc2
      Alan Cox 提交于
      Currently we reinit the ldisc on final tty close which is what the old code
      did to ensure that if the device retained its termios settings then it had the
      right ldisc. tty_ldisc_reinit does that but also leaves us with the reset
      ldisc reference which is then leaked.
      
      At this point we know the port will be recycled so we can kill the ldisc
      off completely rather than try and add another ldisc free up when the kref
      count hits zero.
      
      At this point it is safe to keep the ldisc closed as tty_ldisc waiting
      methods are only used from the user side, and as the final close we are
      the last such reference. Interrupt/driver side methods will always use the
      non wait version and get back a NULL.
      
      Found with kmemleak and investigated/identified by Catalin Marinas.
      Signed-off-by: NAlan Cox <alan@linux.intel.com>
      Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
      aef29bc2
  19. 17 6月, 2009 4 次提交
  20. 11 6月, 2009 4 次提交
  21. 01 4月, 2009 1 次提交
  22. 03 1月, 2009 1 次提交
  23. 02 8月, 2008 1 次提交
  24. 23 7月, 2008 1 次提交