Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 16: Page and Buffer Cache


The implementation ofgrow_buffersis not especially lengthy. A few correctness checks are carried
out before work is delegated to thegrow_dev_pagefunction whose code flow diagram is shown in
Figure 16-10.

Create buffers

grow_dev_page

find_or_create_page

link_dev_buffers

init_page_buffers

Figure 16-10: Code flow diagram for
grow_dev_page.

The function first invokesfind_or_create_pageto a suitable page or generates a new page to hold the
buffer data.

Of course, this and other allocation operations will fail if insufficient memory is available. In this case,
the function returns a null pointer, thus causing the complete cycle to be repeated in__getblk_slow
until sufficient memory is available. This also applies for the other functions that are invoked so there is
no need to mention them explicitly.

If the page is already associated with a buffer of the correct size, the remaining buffer data (b_bdevand
b_blocknr)aremodifiedbyinit_page_buffers.grow_dev_pagethen has nothing else to do and can be
exited.

Otherwise,alloc_page_buffersgenerates a new set of buffers that can be attached to the
page using the familiarlink_dev_buffersfunction.init_page_buffersis invoked to fill the status
(b_status)and the management data (b_bdev,b_blocknr) of the buffer heads.

The function__bread


In contrast to the methods just described,__breadensures that an up-to-date buffer is returned. The
function is not difficult to implement as it builds on__getblk:

fs/buffer.c
__bread(struct block_device *bdev, sector_t block, int size)
{
struct buffer_head *bh = __getblk(bdev, block, size);

if (likely(bh) && !buffer_uptodate(bh))
bh = __bread_slow(bh);
return bh;
}

The first action is to invoke the__getblkroutine to make sure that memory is present for the buffer head
and data contents. A pointer to the buffer is returned if the buffer is already up-to-date.
Free download pdf