struct page {

unsigned long private; /* Mapping-private opaque data */

The private element can also be used for various other purposes that, depending on page use, need have nothing to do with buffers.10 However, its predominant use is to link buffers and pages. In this case, private points to the first buffer head used to split the page into smaller units. The various buffer heads are linked in a cyclic list by means of b_this_page. In this list, each pointer points to the next buffer, and the b_this_page element of the last buffer head points to the first buffer. This enables the kernel to easily scan all buffer_head instances associated with the page, starting from the page structure.

How is the association between the page and the buffer_head structures established? The kernel provides the create_empty_buffers and link_dev_buffers functions for this purpose, both of which are implemented in fs/buffer.c. The latter serves to associate an existing set of buffer heads with a page, whereas create_empty_buffers generates a completely new set of buffers for association with the page. For example, create_empty_buffers is invoked when reading and writing complete pages with block_read_full_page and_block_write_full_page.

create_empty_buffers first invokes alloc_page_buffers to create the required number of buffer heads (this number varies according to page and block size). It returns a pointer to the first element of a singly

10If the page resides in the swap cache, an instance of swp_entry_t is also stored in the cache. If the page is not in use, the element holds the order in the buddy system.

linked list in which each b_this_page element points to the next buffer. The only exception is the last buffer, where b_this_page holds a null pointer:

Continue reading here: Fsbufferc

Was this article helpful?

0 0