2016-12-31
本文主要解释BH_New的含义, 以及何时设置该标志.

1. set_buffer_new

linux-3.10.86/fs/ext2/inode.c

static int ext2_get_blocks(struct inode *inode,
               sector_t iblock, unsigned long maxblocks,
               struct buffer_head *bh_result,
               int create)
{


    /*
    在查找@iblock的过程中, 遇到了指向块0的情况.
    比如ext2_get_blocks()查找iblock为6的映射,
    结果ext2_inode的i_data[5]==0

    假定文件的0-21块都是hole:
    ext2_get_blocks()中查找@iblock为20,
    i_data[12]==0, 那么, 会set_buffer_new;
    下回查找@iblock为21, i_data[12]!=0, 
    不过, i_data的下一级, offset为8的地方, 还是0 ,
    所以, 依旧set_buffer_new.
    也就是说, 查找@iblock为20, 只触发1次set_buffer_new, 而不是2次, 
    因为是在分配好chain所需的块后, 才调用一次set_buffer_new.
    然后查找@iblock为21, 会触发1次set_buffer_new;


    问题:buffer_new()意味着什么?
    答:意味着, 将原先还不属于文件系统的块, 划分给了文件系统.

    */
    set_buffer_new(bh_result);
got_it:
    ...
}

2. unmap_underlying_metadata


__block_write_begin
{
    ...
    err = get_block(inode, block, bh, 1); //比如ext2_get_blocks
    if (err)
        break;
    if (buffer_new(bh)) {
        unmap_underlying_metadata(bh->b_bdev,
                    bh->b_blocknr);
        ...
    }

}


/*
 __block_write_full_page
 {
    create_page_buffers //这里没有从裸块设备的地址空间中查找
    unmap_underlying_metadata
 }
 */
void unmap_underlying_metadata(struct block_device *bdev, sector_t block)
{
    struct buffer_head *old_bh;

    might_sleep();

    old_bh = __find_get_block_slow(bdev, block);//从裸块设备的地址空间中查找
    if (old_bh) {
        clear_buffer_dirty(old_bh);
        /*
        问题:这里没有获取锁, 只是等待他人把锁释放掉, 意义何在?
        答:让两者不要相互干扰.
        */
        wait_on_buffer(old_bh);
        clear_buffer_req(old_bh);
        ...
    }
}

本文地址: https://awakening-fong.github.io/posts/io/set_buffer_new

转载请注明出处: https://awakening-fong.github.io


若无法评论, 请打开JavaScript, 并通过proxy.


blog comments powered by Disqus