Библиотека сайта rus-linux.net
The book is available and called simply "Understanding The Linux Virtual Memory Manager". There is a lot of additional material in the book that is not available here, including details on later 2.4 kernels, introductions to 2.6, a whole new chapter on the shared memory filesystem, coverage of TLB management, a lot more code commentary, countless other additions and clarifications and a CD with lots of cool stuff on it. This material (although now dated and lacking in comparison to the book) will remain available although I obviously encourge you to buy the book from your favourite book store :-) . As the book is under the Bruce Perens Open Book Series, it will be available 90 days after appearing on the book shelves which means it is not available right now. When it is available, it will be downloadable from http://www.phptr.com/perens so check there for more information.
To be fully clear, this webpage is not the actual book.
Next: 10.5 Emergency Pools Up: 10. High Memory Management Previous: 10.3 Mapping High Memory   Contents   Index
Subsections
10.4 Bounce Buffers
Bounce buffers are required for devices that cannot access the full range of memory available to the CPU. An obvious example of this is when a device does not address with as many bits as the CPU, such as 32 bit devices on 64 bit architectures or recent Intel processors with PAE enabled.
The basic concept is very simple. A bounce buffer resides in memory low enough for a device to copy from and write data to. It is then copied to the desired user page in high memory. This additional copy is undesirable, but unavoidable. Pages are allocated in low memory which are used as buffer pages for DMA to and from the device. This is then copied by the kernel to the buffer page in high memory when IO completes so the bounce buffer acts as a type of bridge. There is significant overhead to this operation as at the very least it involves copying a full page but it is insignificant in comparison to swapping out pages in low memory.
10.4.1 Disk Buffering
Blocks, typically around 1KiB are packed into pages and managed by a
struct
buffer_head
allocated by the slab
allocator. A user of buffer heads has the option of having a callback function
registered in the buffer_head
as b_end_io()
called
when IO completes. It is this mechanism that bounce buffers uses to have data
copied out of the bounce buffers. The callback registered is the function
bounce_end_io_write()
.
Any other feature of buffer heads or how they are used by the block layer is beyond the scope of this document and more the concern of the IO layer.
10.4.2 Creating Bounce Buffers
The creation of a bounce buffer is a simple affair which is started by the
create_bounce()
function. The principle is very simple, create a
new buffer using a provided buffer head as a template. The function takes two
parameters which are a read/write parameter (rw
) and the template
buffer head to use (bh_orig
).
A page is allocated for the buffer itself with the function
alloc_bounce_page()
which is a wrapper around
alloc_page()
with one important addition. If the allocation is
unsuccessful, there is an emergency pool of pages and buffer heads available
for bounce buffers. This is discussed further in Section 10.5.
The buffer head is, predictably enough, allocated with
alloc_bounce_bh()
which, similar in principle to
alloc_bounce_page()
, calls the slab allocator for a
buffer_head
and uses the emergency pool if one cannot be
allocated. Additionally, bdflush is woken up to start flushing
dirty buffers out to disk so that buffers are more likely to be freed soon.
Once the page and buffer_head
have been allocated, information
is copied from the template buffer_head
into the new one. Since
part of this operation may use kmap_atomic()
, bounce buffers
are only created with the IRQ safe io_request_lock
held. The IO
completion callbacks are changed to be either bounce_end_io_write()
or bounce_end_io_read()
depending on whether this is a read or
write buffer so the data will be copied to and from high memory.
The most important aspect of the allocations to note is that the GFP flags specify that no IO operations involving high memory may be used10.4. This is important as bounce buffers are used for IO operations with high memory. If the allocator tries to perform high memory IO, it will recurse and eventually crash.
10.4.3 Copying via bounce buffers
Data is copied via the bounce buffer differently depending on whether it is a
read or write buffer. If the buffer is for writes to the device, the buffer
is populated with the data from high memory during bounce buffer creation
with the function copy_from_high_bh()
. The callback function
bounce_end_io_write()
will complete the IO later when the device
is ready for the data.
If the buffer is for reading from the device, no data transfer may take
place until the device is ready. When it is, the interrupt handler for the
device calls the callback function bounce_end_io_read()
which
copies the data to high memory with copy_to_high_bh_irq()
.
In either case the buffer head and page may be reclaimed by
bounce_end_io()
once the IO has completed and the IO completion
function for the template buffer_head()
is called. If the emergency
pools are not full, the resources are added to the pools otherwise they are
freed back to the respective allocators.
Footnotes
- ... used10.4
- This
is specified with
SLAB_NOHIGHIO
to the slab allocator andGFP_NOHIGHIO
to the buddy allocator.
Next: 10.5 Emergency Pools Up: 10. High Memory Management Previous: 10.3 Mapping High Memory   Contents   Index Mel 2004-02-15