set_bh_page 对页面缓存中给定的缓冲区头到底做了什么?

What exactly set_bh_page does for a given buffer head in page cache?

我正在研究内核源代码,我注意到了这个函数 set_bh_page()。但是,我没看清楚它的作用。

我只能在 fs/buffer.c 文件中找到这条评论:

/* Link the buffer to its page */

set_bh_page(bh, page, offset);

但我仍然不清楚它的作用。

所以,为了说清楚,我想了解一下这个函数调用对buffer和物理page是什么关系,以及是否和page cache本身有什么关系。

更新 1:

函数alloc_page_buffers()调用了这个set_bh_page(),对此有一些评论,如下:

Create the appropriate buffers when a given a page for data area and the size of each buffer.. User the bh->b_this_page linked list to follow the buffers created. Return NULL if unable to create more buffers.

然后我检查了谁调用了 alloc_page_buffers(),其中一个是 read_page(),描述如下:

Read a page from a file.

We both read the page, and attach buffers to the page to record the address of each block (using bmap). These addresses will be used to write the block later, completely bypassing the filesystem. This usage is similar to how swap files are handled, and allows us to write to a file with no concerns of memory allocation failing.

所以,通过查看read_page()的源代码,我的理解是分配的buffer_head必须关联到它的物理页地址,就像直接映射一样。

对吗?

当内核需要从块设备访问一个块时,发现页面缓存中没有包含该块的页面,它会分配一个页面,称为块设备缓冲页 或只是一个 缓冲页 ,然后将请求的块写入其中。进程从grow_buffers function, which calls alloc_page_buffers开始,声明如下:

struct buffer_head *alloc_page_buffers(struct page *page, unsigned long size, bool retry);

page 指向将要保存该块的缓冲区页的描述符。 size表示一个块的大小,以字节为单位,其中缓冲页的所有块大小相同。请注意,块是块设备的内存区域,而缓冲区是主内存的内存区域。缓冲区保存单个块的数据,并且大小相同。所以缓冲页看起来像这样:

       .
       .
       .
|-------------|
|    buffer   |
|-------------|
|    buffer   |
|-------------|
|    buffer   |
|-------------|
       .
       .
       .

每个缓冲区中包含的块由缓冲区头标识。您可以找到 buffer_head here 的结构声明。 b_bdevb_blocknr 字段一起标识块设备上的块。请注意,每个缓冲区头都有一个指向同一缓冲区页内下一个缓冲区头的指针。 alloc_page_buffers函数分配并初始化指定缓冲页的所有缓冲区的缓冲头。 alloc_page_buffers调用set_bh_page函数初始化buffer head的两个特定字段,b_pageb_data,代码中注释描述:

struct page *b_page;    /* the page this bh is mapped to */
char        *b_data;    /* pointer to data within the page */

如您所见,"links the buffer to its page"。