缓冲区头¶
Linux 使用缓冲区头来维护关于各个文件系统块的状态。缓冲区头已被弃用,新的文件系统应使用 iomap 代替。
函数¶
-
void brelse(struct buffer_head *bh)¶
释放缓冲区。
参数
struct buffer_head *bh
要释放的缓冲区。
描述
减少 buffer_head 的引用计数。如果 bh 为 NULL,则此函数为空操作。
如果一个页上所有缓冲区的引用计数均为零,都是干净且未锁定的,并且如果该页已解锁且未处于写回状态,则 try_to_free_buffers()
可能会从该页中剥离缓冲区,以便准备释放它(有时,很少,缓冲区会从一个页中删除,但最终不会被释放,并且缓冲区可能会稍后重新附加)。
上下文
任何上下文。
-
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
要跳过的缓冲区数量。
描述
这主要用于查找页中的第 n 个缓冲区;在这种情况下,您传递头缓冲区以及页中的字节偏移量除以块大小。它也可以用于其他目的,但它会在页的末尾环绕,而不是返回 NULL 或继续到下一个页。
返回
请求的缓冲区,其引用计数已增加。
-
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)¶
用于没有 inode 锁的简单文件系统的通用缓冲区 fsync 实现
参数
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)¶
用于没有 inode 锁的简单文件系统的通用缓冲区 fsync 实现
参数
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)¶
将页标记为脏。
参数
struct address_space *mapping
包含此页的地址空间。
struct folio *folio
要标记为脏的页。
描述
使用 buffer_heads 的文件系统可以使用此函数作为其 ->dirty_folio 实现。某些文件系统需要在调用此函数之前做一些工作。不使用 buffer_heads 的文件系统应调用 filemap_dirty_folio()
代替。
如果页有缓冲区,则会将最新的缓冲区设置为脏,以保持页和缓冲区之间的脏状态一致性。添加到脏页的缓冲区将被创建为脏。
缓冲区会在页被标记为脏之前被弄脏。写回可能会看到页的清洁度,但看不到缓冲区的脏度,这有一个很小的竞争窗口。这没关系。如果此代码要在缓冲区之前设置页为脏,写回可能会清除页的脏标志,看到一堆干净的缓冲区,并且我们最终会得到脏缓冲区/脏页列表上的干净页。
我们使用 i_private_lock 来防止在使用 folio 的缓冲区列表时出现与 try_to_free_buffers()
的冲突。这也可以防止在 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)¶
释放缓冲区。
-
void __bforget(struct buffer_head *bh)¶
丢弃缓冲区中的任何脏数据。
-
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_head 的大小。
gfp_t gfp
要使用的内存分配标志。
描述
返回的 buffer head 的引用计数已递增,但未锁定。调用者在完成对缓冲区的使用后应调用 brelse()
。缓冲区可能不是最新的。如果需要,调用者可以通过读取或覆盖来使其保持最新。
返回
buffer head,如果无法分配内存,则为 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()
中的一个。
读取指定的块,并返回指向它的 buffer head。如果 gfp 为 0,则将使用块设备的默认 GFP 标志分配内存。如果 gfp 为 __GFP_MOVABLE,则可以从可移动区域分配内存。请勿传入完整的 GFP 标志集。
返回的 buffer head 的引用计数已增加。调用者在完成对缓冲区的使用后应调用 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 操作会更有效。这种情况就发生在这里。
参数
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。