2016-12-30
do_generic_file_read和generic_perform_write中对锁的处理.
从磁盘读到RAM中的过程中, page需要处于lock状态.
把用户的数据拷贝到page cahe, 该过程也要处理好lock page问题.

1. do_generic_file_read中的lock page

linux-3.10.86/mm/filemap.c

do_generic_file_read
{

    if (!PageUptodate(page)) {

        if ( ... || !mapping->a_ops->is_partially_uptodate)
            goto page_not_up_to_date;

        unlock_page(page);

    }

page_not_up_to_date:
    error = lock_page_killable(page);

page_not_up_to_date_locked:
...
    /* Start the actual read. The read will unlock the page. */
    error = mapping->a_ops->readpage(filp, page);

    if (!PageUptodate(page)) {
                /*
                a_ops->readpage会立刻返回吗? 
                答:是的, 通常是submit_bh或submit_bio后就返回了, 
                所以, lock_page_killable()就是在
                等a_ops->readpage中的设置的I/O completion handler的unlock.
                比如end_buffer_async_read中的unlock_page();
                */
                error = lock_page_killable(page);
                ...
    }

}
  1. 读的发起者 lock_page
  2. 读的发起者 a_ops->readpage()
  3. 读的发起者不必unlock_page, 而是由io complete handler来完成.

2. generic_perform_write 填充page cache

generic_perform_write
{

    a_ops->write_begin(...); //这里面lock_page
    ...
    copied = iov_iter_copy_from_user_atomic(page, i, offset, bytes);
    ...
    a_ops->write_end(...); //这里面unlock_page
}


block_write_begin
{
    page = grab_cache_page_write_begin(mapping, index, flags); //内有lock page

}

ext2_write_end -> generic_write_end()
{
    ...
    /* 填好page cache, 剩下是write back的事了*/
    unlock_page(page);

}

3. write_cache_pages 回写

linux-3.10.86/mm/page-writeback.c

write_cache_pages
{

    while (...) {

        nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, tag,
                  min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
        if (nr_pages == 0)
            break;

        ...
            lock_page(page);
        ...
            /*常见的有__mpage_writepage 或者 __writepage*/
            ret = (*writepage)(page, wbc, data);


}
__block_write_full_page
{

    /*
    问题:这个是和哪里对应的?
    答:
    write_cache_pages
    |--lock_page
    |--writepage -> __writepage -> ext2_writepage -> block_write_full_page -> block_write_full_page_endio -> __block_write_full_page
    */
    unlock_page(page);
}


4. more ...

Documentation/filesystems/Locking

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

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


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


blog comments powered by Disqus