1. 14 Oct, 2009 3 commits
    • Linus Torvalds's avatar
      tty: use the new 'flush_delayed_work()' helper to do ldisc flush · 97ad5a03
      Linus Torvalds authored
      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: default avatarBoyan <btanastasov@yahoo.co.uk>
      Acked-by: default avatarAlan Cox <alan@lxorguk.ukuu.org.uk>
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      97ad5a03
    • Linus Torvalds's avatar
      workqueue: add 'flush_delayed_work()' to run and wait for delayed work · 8c53e463
      Linus Torvalds authored
      It basically turns a delayed work into an immediate work, and then waits
      for it to finish, thus allowing you to force (and wait for) an immediate
      flush of a delayed work.
      
      We'll want to use this in the tty layer to clean up tty_flush_to_ldisc().
      Acked-by: default avatarOleg Nesterov <oleg@redhat.com>
      [ Fixed to use 'del_timer_sync()' as noted by Oleg ]
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      8c53e463
    • Linus Torvalds's avatar
      tty: Make flush_to_ldisc() locking more robust · c8e33141
      Linus Torvalds authored
      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: default avatarFrédéric Meunier <fredlwm@gmail.com>
      Reported-and-tested-by: default avatarBoyan <btanastasov@yahoo.co.uk>
      Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
      Cc: Paul Fulghum <paulkf@microgate.com>
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      c8e33141
  2. 13 Oct, 2009 18 commits
  3. 12 Oct, 2009 19 commits