缓冲区头

Linux 使用缓冲区头来维护关于单个文件系统块的状态。缓冲区头已被弃用,新的文件系统应该使用 iomap 代替。

函数

void brelse(struct buffer_head *bh)

释放缓冲区。

参数

struct buffer_head *bh

要释放的缓冲区。

描述

减少 buffer_head 的引用计数。 如果 bh 为 NULL,则此函数不执行任何操作。

如果一个 folio 上的所有缓冲区都具有零引用计数,是干净且未锁定的,并且如果该 folio 是未锁定且未处于写回状态,则 try_to_free_buffers() 可能会从 folio 中剥离缓冲区,以准备释放它(有时,很少情况下,缓冲区会从 folio 中移除,但最终不会被释放,并且缓冲区可能会稍后重新附加)。

上下文

任何上下文。

void bforget(struct buffer_head *bh)

丢弃缓冲区中的任何脏数据。

参数

struct buffer_head *bh

要忘记的缓冲区。

描述

如果写入缓冲区的数据不再需要写回,则调用此函数而不是 brelse()。 它将清除缓冲区的脏标志,因此将跳过此缓冲区的写回。

上下文

任何上下文。

struct buffer_head *__bread(struct block_device *bdev, sector_t block, unsigned size)

读取一个块。

参数

struct block_device *bdev

要读取的块设备。

sector_t block

块号,以块大小为单位。

unsigned size

此设备的块大小(以字节为单位)。

描述

读取指定的块,并返回引用它的缓冲区头。内存从可移动区域分配,因此可以迁移。返回的缓冲区头的引用计数已增加。调用者应在完成缓冲区操作后调用 brelse()

上下文

可能会睡眠等待 I/O。

返回值

如果块不可读,则返回 NULL。

struct buffer_head *get_nth_bh(struct buffer_head *bh, unsigned int count)

获取此缓冲区之后的第 n 个缓冲区的引用。

参数

struct buffer_head *bh

开始计数的缓冲区。

unsigned int count

要跳过多少个缓冲区。

描述

这主要用于查找 folio 中的第 n 个缓冲区; 在这种情况下,您传递头部缓冲区和 folio 中的字节偏移量除以块大小。 它可用于其他目的,但它将在 folio 的末尾环绕,而不是返回 NULL 或继续到下一个 folio。

返回值

请求的缓冲区,引用计数已提升。

int sync_mapping_buffers(struct address_space *mapping)

写出并等待映射的“关联”缓冲区

参数

struct address_space *mapping

想要写入这些缓冲区的映射

描述

针对 mapping->i_private_list 中的缓冲区启动 I/O,并等待该 I/O。

基本上,这是 fsync() 的一个方便函数。 mapping 是一个文件或目录,需要写入这些缓冲区才能成功执行 fsync()。

int generic_buffers_fsync_noflush(struct file *file, loff_t start, loff_t end, bool datasync)

用于简单文件系统的通用缓冲区 fsync 实现,没有 inode 锁

参数

struct file *file

要同步的文件

loff_t start

起始偏移量(以字节为单位)

loff_t end

结束偏移量(以字节为单位)(包含)

bool datasync

如果为 true,则仅同步必要的元数据

描述

这是 fsync 方法的通用实现,适用于在挂在 address_space 结构上的缓冲区列表中跟踪所有非 inode 元数据的简单文件系统。

int generic_buffers_fsync(struct file *file, loff_t start, loff_t end, bool datasync)

用于简单文件系统的通用缓冲区 fsync 实现,没有 inode 锁

参数

struct file *file

要同步的文件

loff_t start

起始偏移量(以字节为单位)

loff_t end

结束偏移量(以字节为单位)(包含)

bool datasync

如果为 true,则仅同步必要的元数据

描述

这是 fsync 方法的通用实现,适用于在挂在 address_space 结构上的缓冲区列表中跟踪所有非 inode 元数据的简单文件系统。 这也确保在最后调用设备缓存刷新操作。

bool block_dirty_folio(struct address_space *mapping, struct folio *folio)

将 folio 标记为脏。

参数

struct address_space *mapping

包含此 folio 的地址空间。

struct folio *folio

要标记为脏的 folio。

描述

使用 buffer_heads 的文件系统可以使用此函数作为其 ->dirty_folio 实现。 某些文件系统需要在调用此函数之前做一些工作。 不使用 buffer_heads 的文件系统应改为调用 filemap_dirty_folio()

如果 folio 有缓冲区,则更新的缓冲区将设置为脏,以保持 folio 和缓冲区之间的脏状态一致性。 添加到脏 folio 的缓冲区会被创建为脏缓冲区。

缓冲区在 folio 被标记为脏之前被标记为脏。 存在一个小的竞争窗口,其中写回可能会看到 folio 的干净状态,但看不到缓冲区的脏状态。 这没关系。 如果此代码要在缓冲区之前设置 folio 脏标志,写回可能会清除 folio 脏标志,看到一堆干净的缓冲区,最终我们会在脏 folio 列表中得到脏缓冲区/干净 folio。

我们使用 i_private_lock 来锁定 try_to_free_buffers(),同时使用 folio 的缓冲区列表。 这也防止在 folio 设置为脏后将干净的缓冲区添加到 folio。

上下文

只能从进程上下文中调用。 不会睡眠。 调用者必须确保在此调用期间无法截断 folio,通常是通过持有 folio 锁或在 folio 中映射一个页面并持有页表锁。

返回值

如果 folio 被标记为脏,则为 True; 如果已标记为脏,则为 false。

void mark_buffer_dirty(struct buffer_head *bh)

将 buffer_head 标记为需要写出

参数

struct buffer_head *bh

要标记为脏的 buffer_head

描述

mark_buffer_dirty() 将针对缓冲区设置脏位,然后将它的支持页面设置为脏,然后在页面缓存中将页面标记为脏,然后将 address_space 的 inode 附加到其超级块的脏 inode 列表。

mark_buffer_dirty() 是原子的。 它采用 bh->b_folio->mapping->i_private_lock、i_pages 锁和 mapping->host->i_lock。

void __brelse(struct buffer_head *bh)

释放缓冲区。

参数

struct buffer_head *bh

要释放的缓冲区。

描述

如果保证 bh 不为 NULL,则可以调用此 brelse() 的变体。

void __bforget(struct buffer_head *bh)

丢弃缓冲区中的任何脏数据。

参数

struct buffer_head *bh

要忘记的缓冲区。

描述

如果保证 bh 不为 NULL,则可以调用此 bforget() 的变体。

struct buffer_head *bdev_getblk(struct block_device *bdev, sector_t block, unsigned size, gfp_t gfp)

在块设备的缓冲区缓存中获取 buffer_head。

参数

struct block_device *bdev

块设备。

sector_t block

块号。

unsigned size

bdev 的 buffer_heads 的大小。

gfp_t gfp

要使用的内存分配标志。

描述

返回的缓冲区头的引用计数已递增,但未锁定。 调用者应在完成缓冲区操作后调用 brelse()。 缓冲区可能不是最新的。 如果需要,调用者可以通过读取它或覆盖它来使其保持最新。

返回值

缓冲区头,如果无法分配内存,则为 NULL。

struct buffer_head *__bread_gfp(struct block_device *bdev, sector_t block, unsigned size, gfp_t gfp)

读取一个块。

参数

struct block_device *bdev

要读取的块设备。

sector_t block

块号,以块大小为单位。

unsigned size

此设备的块大小(以字节为单位)。

gfp_t gfp

不是页面分配标志; 请参阅下文。

描述

您不应调用此函数。 您应该使用 sb_bread()、sb_bread_unmovable() 或 __bread() 之一。

读取指定的块,并返回引用它的缓冲区头。 如果 gfp 为 0,则将使用块设备的默认 GFP 标志分配内存。 如果 gfp 为 __GFP_MOVABLE,则可以从可移动区域分配内存。 不要传入完整的 GFP 标志集。

返回的缓冲区头的引用计数已增加。 调用者应在完成缓冲区操作后调用 brelse()

上下文

可能会睡眠等待 I/O。

返回值

如果块不可读,则返回 NULL。

void block_invalidate_folio(struct folio *folio, size_t offset, size_t length)

使缓冲区支持的 folio 的部分或全部失效。

参数

struct folio *folio

受影响的 folio。

size_t offset

要失效的范围的开始

size_t length

要失效的范围的长度

描述

当 folio 的全部或部分被截断操作失效时,将调用 block_invalidate_folio()

block_invalidate_folio() 不必释放所有缓冲区,但它必须确保在 offset 之外没有留下任何脏缓冲区,并且没有针对截断点之外的任何块进行 I/O。 因为调用者将要释放(并可能重用)磁盘上的那些块。

void clean_bdev_aliases(struct block_device *bdev, sector_t block, sector_t len)

清理块设备中的一系列缓冲区

参数

struct block_device *bdev

要在其中清理缓冲区的块设备

sector_t block

要清理的块范围的开始

sector_t len

要清理的块数

描述

我们正在获取一系列块用于数据,并且我们不希望从该函数返回开始,直到显式将缓冲区标记为脏的时刻(希望在我们释放该块之前不会发生这种情况 ;-) 我们甚至不需要将其标记为非最新的 - 无论如何,没有人可以对新分配的缓冲区有任何期望。 我们过去使用 unmap_buffer() 进行这种失效,但这是不正确的。 例如,我们绝对不想将别名标记为未映射 - 这会混淆任何可能使用 bread() 拾取它的人...

此外.. 请注意 bforget() 不会锁定缓冲区。 因此,可能会针对最近释放的缓冲区进行写出 I/O。 我们不会在 bforget() 中等待该 I/O - 仅在我们真正需要时才等待 I/O 更有效。 这就是这里发生的事情。

bool try_to_free_buffers(struct folio *folio)

释放附加到此 folio 的缓冲区。

参数

struct folio *folio

该 folio。

描述

如果有任何缓冲区正在使用中(脏、处于写回状态、引用计数已提升),则不会释放任何缓冲区。

如果 folio 是脏的,但所有缓冲区都是干净的,那么我们需要确保也将 folio 标记为干净的。 这是因为 folio 可能是针对块设备的,并且稍后将缓冲区重新附加到脏 folio 将设置所有缓冲区为脏。 这会损坏同一设备上的文件系统数据。

这同样适用于常规文件系统 folio:如果所有缓冲区都是干净的,那么我们将 folio 设置为干净并继续。 为此,我们需要完全排除 block_dirty_folio()。 这是通过 i_private_lock 获得的。

可以通过锁定 folio 或持有其映射的 i_private_lock 来获得针对 try_to_free_buffers 的排除。

上下文

进程上下文。 folio 必须被锁定。 不会睡眠。

返回值

如果附加到此 folio 的所有缓冲区都被释放,则为 true。

int bh_uptodate_or_lock(struct buffer_head *bh)

测试缓冲区是否是最新的

参数

struct buffer_head *bh

struct buffer_head

描述

如果缓冲区是最新的,则返回 true; 如果不是,则返回 false,并且缓冲区被锁定。

int __bh_read(struct buffer_head *bh, blk_opf_t op_flags, bool wait)

提交已锁定缓冲区的读取

参数

struct buffer_head *bh

struct buffer_head

blk_opf_t op_flags

除了 REQ_OP_READ 之外,还附加 REQ_OP_* 标志

bool wait

等待直到读取完成

描述

成功或不等待时返回零,错误时返回 -EIO。

void __bh_read_batch(int nr, struct buffer_head *bhs[], blk_opf_t op_flags, bool force_lock)

提交一批未锁定缓冲区的读取

参数

int nr

缓冲区批次的条目数

struct buffer_head *bhs[]

一批 struct buffer_head

blk_opf_t op_flags

除了 REQ_OP_READ 之外,还附加 REQ_OP_* 标志

bool force_lock

如果设置,则强制获取缓冲区的锁,否则将丢弃任何无法锁定的缓冲区。

描述

成功或不等待时返回零,错误时返回 -EIO。