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