tty flip buffer changes in 2.6.16



One of my patches in vt_ioctl.c needs to change because of this. So I am
analyzing what all this change is about. Thankfully, Alan has included a
thorough description right in the ChangeLog file.

Excepting from ChangeLog-2.6.16:

# commit 33f0f88f1c51ae5c2d593d26960c760ea154c2e2
# Author: Alan Cox <alan+lxorguk.ukuu.org.uk>
# Date: Mon Jan 9 20:54:13 2006 -0800
#
# [PATCH] TTY layer buffering revamp
#
# The API and code have been through various bits of initial review by
# serial driver people but they definitely need to live somewhere for a
# while so the unconverted drivers can get knocked into shape, existing
# drivers that have been updated can be better tuned and bugs whacked out.
#
# This replaces the tty flip buffers with kmalloc objects in rings. In the
# normal situation for an IRQ driven serial port at typical speeds the
# behaviour is pretty much the same, two buffers end up allocated and the
# kernel cycles between them as before.
#
# When there are delays or at high speed we now behave far better as the
# buffer pool can grow a bit rather than lose characters. This also means
# that we can operate at higher speeds reliably.

I've seen character loss on serial ports even at 9600 baud.


# For drivers that receive characters in blocks (DMA based, USB and
# especially virtualisation) the layer allows a lot of driver specific
# code that works around the tty layer with private secondary queues to be
# removed. The IBM folks need this sort of layer, the smart serial port
# people do, the virtualisers do (because a virtualised tty typically
# operates at infinite speed rather than emulating 9600 baud).
#
# Finally many drivers had invalid and unsafe attempts to avoid buffer
# overflows by directly invoking tty methods extracted out of the innards
# of work queue structs. These are no longer needed and all go away. That
# fixes various random hangs with serial ports on overflow.
#
# The other change in here is to optimise the receive_room path that is
# used by some callers. It turns out that only one ldisc uses receive room
# except asa constant and it updates it far far less than the value is
# read. We thus make it a variable not a function call.
#
# I expect the code to contain bugs due to the size alone but I'll be
# watching and squashing them and feeding out new patches as it goes.
#
# Because the buffers now dynamically expand you should only run out of
# buffering when the kernel runs out of memory for real. That means a lot of
# the horrible hacks high performance drivers used to do just aren't needed any
# more.

My patch could create a denial of service exposure in combination with this.
I might need ideas on how to prevent that.


# Description:
#
# tty_insert_flip_char is an old API and continues to work as before, as does
# tty_flip_buffer_push() [this is why many drivers dont need modification]. It
# does now also return the number of chars inserted
#
# There are also
#
# tty_buffer_request_room(tty, len)
#
# which asks for a buffer block of the length requested and returns the space
# found. This improves efficiency with hardware that knows how much to
# transfer.
#
# and tty_insert_flip_string_flags(tty, str, flags, len)
#
# to insert a string of characters and flags
#
# For a smart interface the usual code is
#
# len = tty_request_buffer_room(tty, amount_hardware_says);
# tty_insert_flip_string(tty, buffer_from_card, len);

It sounds like this is what I need to use. My patch is adding an ioctl() call to
allow a process (that has _read_ permission on the tty that will receive the data)
to inject a string of character atomically. That is, if there is not enough room
to inject them all, then none will be injected. That's a lot better than injecting
one character at a time and hoping the string can be completed.


# More description!
#
# At the moment tty buffers are attached directly to the tty. This is causing a
# lot of the problems related to tty layer locking, also problems at high speed
# and also with bursty data (such as occurs in virtualised environments)
#
# I'm working on ripping out the flip buffers and replacing them with a pool of
# dynamically allocated buffers. This allows both for old style "byte I/O"
# devices and also helps virtualisation and smart devices where large blocks of
# data suddenely materialise and need storing.

Like ptys and hacked ioctls.


# So far so good. Lots of drivers reference tty->flip.*. Several of them also
# call directly and unsafely into function pointers it provides. This will all
# break. Most drivers can use tty_insert_flip_char which can be kept as an API
# but others need more.

That's what I _was_ using (up through 2.6.15.6).


# At the moment I've added the following interfaces, if people think more will
# be needed now is a good time to say
#
# int tty_buffer_request_room(tty, size)
#
# Try and ensure at least size bytes are available, returns actual room (may be
# zero). At the moment it just uses the flipbuf space but that will change.
# Repeated calls without characters being added are not cumulative. (ie if you
# call it with 1, 1, 1, and then 4 you'll have four characters of space. The
# other functions will also try and grow buffers in future but this will be a
# more efficient way when you know block sizes.

So it just reports what _could_ be injected right now, based on what is in
there right now.


# int tty_insert_flip_char(tty, ch, flag)
#
# As before insert a character if there is room. Now returns 1 for success, 0
# for failure.
#
# int tty_insert_flip_string(tty, str, len)
#
# Insert a block of non error characters. Returns the number inserted.

I definitely want to use the string method. However, I don't know what he means
by "non error characters". Anyone know what that could be?


# int tty_prepare_flip_string(tty, strptr, len)
#
# Adjust the buffer to allow len characters to be added. Returns a buffer
# pointer in strptr and the length available. This allows for hardware that
# needs to use functions like insl or mencpy_fromio.

So this is a more direct approach than tty_buffer_request_room() ?


# Signed-off-by: Alan Cox <alan+redhat.com>
# Cc: Paul Fulghum <paulkf+microgate.com>
# Signed-off-by: Hirokazu Takata <takata+linux-m32r.org>
# Signed-off-by: Serge Hallyn <serue+us.ibm.com>
# Signed-off-by: Jeff Dike <jdike+addtoit.com>
# Signed-off-by: John Hawkes <hawkes+sgi.com>
# Signed-off-by: Martin Schwidefsky <schwidefsky+de.ibm.com>
# Signed-off-by: Adrian Bunk <bunk+stusta.de>
# Signed-off-by: Andrew Morton <akpm+osdl.org>
# Signed-off-by: Linus Torvalds <torvalds+osdl.org>


--
-----------------------------------------------------------------------------
| Phil Howard KA9WGN | http://linuxhomepage.com/ http://ham.org/ |
| (first name) at ipal.net | http://phil.ipal.org/ http://ka9wgn.ham.org/ |
-----------------------------------------------------------------------------
.