2016-12-31
generic_perform_write
{

        /*
        ==0==计算没有和PAGE_CACHE_SIZE对齐的那部分的大小, 代码中的bytes.

        杂问题:
        假定PAGE_CACHE_SIZE为4, pos为5, iov_iter_count()大于2个PAGE_CACHE_SIZE,
        则offset为1, bytes为3
        所以, 代码中的bytes就是示意图中|///|那部分:
      pos==0    pos==5
        ^         ^
        |         |
        |----|  |-.---|  |----|
                  |///|
                  读取
        */
        offset = (pos & (PAGE_CACHE_SIZE - 1));
        bytes = min_t(unsigned long, PAGE_CACHE_SIZE - offset,
                        iov_iter_count(i));
again:
        /*
        如何防止dead lock可参考
        https://lkml.org/lkml/2015/6/30/631
        */
        iov_iter_fault_in_readable(...);

        /*
        ==1==准备page
        答:
        如果在address_space中没有该pos对应的page, 则分配page并添加到address_space.
        如果没有写完整的一个sector, 则需要先从磁盘读出原sector.
        */
        status = a_ops->write_begin(file, mapping, pos, bytes, flags,
                        &page, &fsdata);

        /*
        ==2==填充page cache
        */
        /*
        flush_dcache_page 见https://awakening-fong.github.io/posts/flush_dcache_page
        */
        if (mapping_writably_mapped(mapping))
            flush_dcache_page(page);
        pagefault_disable();
        copied = iov_iter_copy_from_user_atomic(page, i, offset, bytes);
        pagefault_enable();
        flush_dcache_page(page);
        /*
        ==3==标记为dirty, 处理short write
        short wrtie是让 copied = iov_iter_copy_from_user_atomic(page, i, offset, bytes);复制bytes, 结果实际只复制copied. 若发生short write, 则重来.
        */
        a_ops->write_end(...);

}

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

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


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


blog comments powered by Disqus