address_space和buffer_head的一些field
2016-12-30
1. 问题引入
这里从一个地址空间 到另一个地址空间, 是为啥?
generic_file_fsync
{
struct inode *inode = file->f_mapping->host;
ret = sync_mapping_buffers(inode->i_mapping);
}
sync_mapping_buffers(struct address_space *mapping)
{
struct address_space *buffer_mapping = mapping->private_data;
}
2. 解
linux-3.10.86/include/linux/fs.h
struct address_space {
/*
链表上的node是buffer_head, 本field(private_list)是链表的head:
sync_mapping_buffers -> fsync_buffers_list(,&mapping->private_list)
|--struct buffer_head *bh= BH_ENTRY(list->next)
链表上的node 可以是ext2查找indoe过程的chain涉及的 用来存储pointer的块 所对应的bh.
问题:添加到private_list的代码?
答:
1. mark_buffer_dirty_inode
2. 这个不是重点:fsync_buffers_list()
-> list_add(&bh->b_assoc_buffers, &mapping->private_list);
*/
struct list_head private_list; /* ditto */
/*有时赋值在 mark_buffer_dirty_inode()
从sync_mapping_buffers和fsync_buffers_list来看,
似乎是裸块设备的地址空间.
*/
void *private_data; /* ditto */
} __attribute__((aligned(sizeof(long))));
struct buffer_head {
/*
问题:用途?
用来连接chain的块, see
ext2_alloc_branch -> mark_buffer_dirty_inode
可顺便see fsync_buffers_list
*/
struct list_head b_assoc_buffers; /* associated with another mapping */
/*有时赋值是在mark_buffer_dirty_inode(), 常规文件内容的地址空间.*/
struct address_space *b_assoc_map; /* mapping this buffer is
associated with */
};
/*
调用路径ext2_alloc_branch()
该@inode的 chain上 用来存储pointer的块, @bh与之关联, 对吗?
*/
void mark_buffer_dirty_inode(struct buffer_head *bh, struct inode *inode)
{
struct address_space *mapping = inode->i_mapping;//这个是文件内容的地址空间
/*这个是裸块设备的地址空间, see
ext2_alloc_branch
|--bh = sb_getblk()
|--mark_buffer_dirty_inode
*/
struct address_space *buffer_mapping = bh->b_page->mapping;
mark_buffer_dirty(bh);
if (!mapping->private_data) {
mapping->private_data = buffer_mapping;
} else {
BUG_ON(mapping->private_data != buffer_mapping);
}
if (!bh->b_assoc_map) {
spin_lock(&buffer_mapping->private_lock);
list_move_tail(&bh->b_assoc_buffers,
&mapping->private_list);
bh->b_assoc_map = mapping;
spin_unlock(&buffer_mapping->private_lock);
}
}
EXPORT_SYMBOL(mark_buffer_dirty_inode);
/**
* ext2_alloc_branch - allocate and set up a chain of blocks.
问题:什么是branch?
答:从的原型ext2_alloc_branch(, Indirect *branch),
可知branch就是Indirect, 对吗?
* @inode: owner
* @num: depth of the chain (number of blocks to allocate)
这个参数(@num)在3.10中不见了, 应该就是3.10的@indirect_blks
fong:从一个pointer 跳到最后的data block的路径称为chain,
该过程使用的pointer的个数 称为depth,
比如, 文件偏移量为6的, depth为1,
或者说 无需indirect, 则depth为1.
* @offsets: offsets (in the blocks) to store the pointers to next.
offset含义:在单个块内, 存储pointer的位置, 用相对于该block开头的偏移量来表示的值, 就是offset.
比如, 下面的示意图, 对于block0, offsets为1; 对于block1, offsets为2.
+---+
|-- | +---+
|-- |\->|-- | |-- |
|-- | |-- | |-- |
+---+ |-- |\--> |-- |
|-- | |-- |
+---+ +---+
block0 block1 data block
*/
static int ext2_alloc_branch(struct inode *inode,
int indirect_blks, int *blks, ext2_fsblk_t goal,
int *offsets, Indirect *branch)
{
...
bh = sb_getblk(inode->i_sb, new_blocks[n-1]);
...
mark_buffer_dirty_inode(bh, inode);
}
fsync_buffers_list
{
while (!list_empty(list)) {
}
while (!list_empty(&tmp)) {
if (buffer_dirty(bh)) {
/*
由于write_dirty_buffer在写入前, 会清掉bh的dirty,
到这里出现dirty的话, 大概是写入完成后, 又被人重新dirty了.
等待下回generic_file_fsync -> sync_mapping_buffers
-> sync_mapping_buffers -> fsync_buffers_list 写入.
*/
list_add(&bh->b_assoc_buffers,
&mapping->private_list);
bh->b_assoc_map = mapping;
}
}
}
本文地址: https://awakening-fong.github.io/posts/io/field_of_bh_and_address_space
转载请注明出处: https://awakening-fong.github.io
若无法评论, 请打开JavaScript, 并通过proxy.
blog comments powered by Disqus