Linux块设备IO子系统(二)(4)

struct buffer_head
--63-->缓冲区状态标志
--64-->指向缓冲区的链表中的下一个元素的指针
--65-->指向拥有该块的缓冲区页的描述符的指针
--67-->块引用计数
--68-->块大小
--69-->表示块缓冲区在缓冲区页中的位置,实际上,这个位置的编号依赖于页是否在高端内存,如果在高端内存,则b_data字段存放的是块缓冲区相对于页的起始位置的偏移量,否则,b_data存放的是块缓冲区的线性地址
--71-->指向IO完成方法数据的指针
--72-->IO完成方法
--73-->指向IO完成方法数据的指针
--74-->为与某个索引节点相关的间接块的链表提供的指针

下面是b_state可能的取值

//include/linux/buffer_head.h 19 enum bh_state_bits { 20 BH_Uptodate, /* Contains valid data */ 21 BH_Dirty, /* Is dirty */ 22 BH_Lock, /* Is locked */ 23 BH_Req, /* Has been submitted for I/O */ 24 BH_Uptodate_Lock,/* Used by the first bh in a page, to serialise 25 * IO completion of other buffers in the page 26 */ 27 28 BH_Mapped, /* Has a disk mapping */ 29 BH_New, /* Disk mapping was newly created by get_block */ 30 BH_Async_Read, /* Is under end_buffer_async_read I/O */ 31 BH_Async_Write, /* Is under end_buffer_async_write I/O */ 32 BH_Delay, /* Buffer is not yet allocated on disk */ 33 BH_Boundary, /* Block is followed by a discontiguity */ 34 BH_Write_EIO, /* I/O error on write */ 35 BH_Unwritten, /* Buffer is allocated on disk but not written */ 36 BH_Quiet, /* Buffer Error Prinks to be quiet */ 37 BH_Meta, /* Buffer contains metadata */ 38 BH_Prio, /* Buffer should be submitted with REQ_PRIO */ 39 BH_Defer_Completion, /* Defer AIO completion to workqueue */ 40 41 BH_PrivateStart,/* not a state bit, but the first bit available 42 * for private allocation by other entities 43 */ 44 }; 增

将块设备缓冲区所在的页添加到页高速缓存中

static int grow_buffers(struct block_device *bdev, sector_t block, int size)

将块设备缓冲区所在的页从页高速缓存中剔除

int try_to_free_buffers(struct page *page) int try_to_release_page(struct page *page, gfp_t gfp_mask)

在页高速缓存中搜索块
当内核需要读写一个单独的物理设备块时(例如一个超级块),必须检查所有请求的块,缓冲区是否已经在页高速缓存中。在页高速缓存中搜索执行的块缓冲区(由块设备描述符的地址bdev和逻辑块号nr表示)的过程可以分成3个步骤

获取一个指针,让它指向包含指定的块设备的address_space对象(bdev->bd_inode->imapping)

获取块设备的大小(bdev->bd_block_size),并计算包含指定块的页索引。这需要在逻辑块号上进行移位操作,eg,如果块的大小是1024字节,每个缓冲区页包含4个块缓冲区,那么页的索引是nr/4

在块设备的基树中搜索缓冲区页,获得页描述符后,内核访问缓冲区首部,它描述了页中块缓冲区的状态

__find_get_block(struct block_device *bdev, sector_t block, unsigned size) __getblk(struct block_device *bdev, sector_t block, unsigned size) __bread(struct block_device *bdev, sector_t block, unsigned size) 交

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/4ca64b8b1a5f9dbca329cf4c31e7b0aa.html