博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
cephfs linux kernel client针对linux page cache的操作
阅读量:5878 次
发布时间:2019-06-19

本文共 5701 字,大约阅读时间需要 19 分钟。

hot3.png

针对linux page cache的操作主要体现在struct address_space_operations数据结构中,cephfs处理linux page cache的函数集合如下:

const struct address_space_operations ceph_aops = {

        .readpage = ceph_readpage,

        .readpages = ceph_readpages,

        .writepage = ceph_writepage,

        .writepages = ceph_writepages_start,

        .write_begin = ceph_write_begin,

        .write_end = ceph_write_end,

        .set_page_dirty = ceph_set_page_dirty,

        .invalidatepage = ceph_invalidatepage,

        .releasepage = ceph_releasepage,

        .direct_IO = ceph_direct_io,

};

 

ceph_readpage(struct file *filp, struct page *page)

|__调用readpage_nounlock(filep, page)     在加锁的情况下读取一个物理内存页的数据

    |__确定page的offset没有超出inode的总长度

    |__调用ceph_readpage_from_fscache()函数尝试从fscache中读取一个物理内存页的数据

        |__若读取成功则直接返回

    |__调用ceph_osdc_readpages()函数从ceph集群中读取一个物理内存页的数据

        |__调用ceph_osdc_new_reqeust()函数创建一个读请求

        |__调用osd_req_op_extent_osd_data_pages()函数为读请求的返回内容分配内存空间

        |__调用ceph_osdc_start_request()函数将读请求同步发送给ceph集群

    |__调用flush_dcache_page()函数刷page到dcache中

    |__调用SetPageUptodate()函数设置物理内存页的状态是update的

    |__调用ceph_readpage_to_fscache()函数将新读到的物理内存页更新到fscache中

|__调用unlock_page(page)

    |__调用clear_bit_unlock()函数为page解锁

    |__调用wake_up_page()函数唤醒等待该page的相关进程

 

ceph_readpages(struct file *file, struct address_space *mapping, struct list_head *page_list, unsigned nr_pages)    读取多个页

|__调用ceph_readpages_from_fscache()函数尝试从fscache中读取多个物理内存页的数据

    |__若读取成功则直接返回

|__遍历page_list

    |__调用start_read()函数读取数据到page_list所包含的物理内存页

        |__调用ceph_osdc_new_reqeust()函数创建一个读请求

        |__调用calc_pages_for(0, len)函数得到读取指定长度len的数据需要的物理内存页数

        |__从page_list中摘下指定数量的物理内存页

        |__调用osd_req_op_extent_osd_data_pages()函数将从page_list中摘下的物理内存页作为读请求的接收缓冲

        |__设置读请求完成后的回调函数为finish_read()

        |__调用ceph_osdc_start_request()函数将读请求同步发送给ceph集群

 

finish_read(struct ceph_osd_request *req)        从ceph集群中读操作结束后的回调函数

|__遍历读取到的所有物理内存页

    |__调用flush_dcache_page()函数将page中的内存刷到dcache中

    |__调用SetPageUptodate()函数设置page的状态是uptodate的

    |__调用ceph_readpage_to_fscache()函数将读取到的page内存同步到fscache中

 

ceph_writepage(struct page *page, struct writeback_control *wbc)

|__调用writepage_nounlock(page,wbc)函数同步page信息到ceph集群

    |__调用page_snap_context()函数得到page的snap context信息(page将CephSnapContext信息写入到page的private中)

    |__调用set_page_writeback(page)函数设置page writeback标识

    |__调用ceph_osdc_writepages()函数将page信息同步写到ceph集群

        |__调用ceph_osdc_new_reqeust()函数创建一个写请求

        |__调用osd_req_op_extent_osd_data_pages()函数为写请求设置写内容物理内存页

        |__调用ceph_osdc_start_request()函数将写请求同步发送给ceph集群

    |__设置page->private=0,即:删除page的CephSnapContext信息

    |__调用ClearPagePrivate(page)函数清空page的private

    |__调用end_page_writeback()函数

        |__调用wake_up_page(page, PG_writeback)函数唤醒在page上等待writeback完成的进程

 

ceph_writepages_start(struct address_space *mapping, struct writeback_control *wbc)

|__调用pagevec_init(&pvec, 0)函数初始化struct pagevec实例pvec

|__从wbc的range_start和range_end中得到start和end

|__调用pagevec_lookup_tag(&pvec, mapping, PAGECACHE_TAG_DIRTY…)函数从mapping中radix tree中找到tags==PAGECACHE_TAG_DIRTY的所有pages且将所有pages写入到pvec中

|__遍历所有PAGECACHE_TAG_DIRTY的pages

    |__调用page_offset()函数得到page所在的offset值

    |__调用ceph_calc_file_object_mapping()函数得到从offset开始,长度是len的文件所占用的objects个数以及在object中的偏移

    |__将page添加到pages数组中

|__从pages数组中得到offset值,即:offset=page_offset(pages[0])

|__调用ceph_osdc_new_request()函数创建一个写数据请求

|__设置写数据请求的回调函数为writepages_finish

|__调用osd_req_op_extent_osd_data_pages()函数添加写请求额外的数据

|__调用ceph_osdc_start_request()函数将写请求同步发送到ceph集群

 

writepages_finish(struct ceph_osd_request *req)

|__清除所有在发送写请求过程中产生的内存

 

ceph_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigend flags, staruct page **pagep, void **fsdata)

|__得到pos所在的page位置,即:index=pos >> PAGE_SHIFT

|__调用grab_cache_page_write_begin(mapping, index, flags)函数在pagecache中指定位置index出获取或创建一个物理内存页page

    |__调用pagecache_get_page()函数在pagecache中指定位置index出获取或创建一个物理内存页page

    |__调用wait_for_stable_page(page)函数等待该page上的writeback函数返回

|__调用ceph_update_writeable_page(file, pos, len, page)函数只允许往clean page里写入数据或者已经dirty的snap context里写入数据

    |__调用wait_on_page_writeback(page)函数等待page的writeback完成

    |__调用page_snap_context(page)函数得到该page的snap context

    |__若snap context的seq > oldest->seq

        |__调用ceph_queue_writeback(inode)函数将inode放入到writeback队列中

    |__调用clear_page_dirty_for_io(page)函数清除page上的dirty标识

    |__调用writepage_nounlock(page, NULL)函数将page数据同步的写入到ceph集群

    |__调用PageUptodate(page)检查page是否是uptodate的

        |__是则直接返回

    |__若page已经满了

        |__直接返回

    |__调用i_size_read(inode)函数得到inode的读数据的大小

    |__调用readpage_nounlock(file, page)函数从ceph集群中读取数据到page中

 

ceph_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, struct page **page, void *fsdata)

|__若copied < len

    |__调用zero_user_segment(page, from+copied, len)函数将page中从from+copied一直到from+copied+len的内存空间置0

|__若pos+copied > i_size_read(inode)

    |__调用ceph_inode_set_size()函数设置inode的size为pos+copied

|__若Page不是uptodate的

    |__调用SetPageUptodate(page)函数设置page是uptodate的

|__调用set_page_dirty(page)函数设置page是dirty的

 

ceph_set_page_dirty(struct page *page)

|__若PageDirty(page)

    |__直接返回

|__通过mapping的到struct ceph_inode_info结构

|__调用__ceph_have_pending_cap_snap()函数检查cephfs是否有snaps

    |__从struct ceph_inode_info结构中的i_cap_snaps列表中得到struct ceph_cap_snap结构

    |__从struct ceph_cap_snap结构中得到struct ceph_snap_context结构

|__若cephfs没有snaps

    |__调用ceph_get_snap_context()函数从struct ceph_inode_info的i_head_spapc中得到struct ceph_snap_context结构

|__将struct ceph_snap_context结构设置到page的private中,即:page->private=snapc

|__调用__set_page_dirty_nobuffers()函数将page在address_spaces中的radix tree中设置成dirty

 

ceph_invalidatepage(struct page *page, unsigned int offset, unsigned int length)

|__调用ceph_invalidate_fscache_page()函数使得page在fscache中无效

|__若page没有private

    |__直接返回

|__设置page->private=0清除page的snaps

|__调用ClearPagePriavte(page)

 

ceph_releasepage(struct page *page, gfp_t g)

|__调用ceph_release_fscache_page()函数在fscache中删除page

|__返回!PagePrivate(page)

 

ceph_direct_io(struct kiocb *iocb, struct iov_iter *iter)

|__返回-EINVAL

转载于:https://my.oschina.net/linuxhunter/blog/732859

你可能感兴趣的文章
小米手机解锁bootload教程及常见问题
查看>>
Python内置函数property()使用实例
查看>>
Spring MVC NoClassDefFoundError 问题的解决方法。
查看>>
CentOS 6.9配置网卡IP/网关/DNS命令详细介绍及一些常用网络配置命令(转)
查看>>
python基础教程_学习笔记19:标准库:一些最爱——集合、堆和双端队列
查看>>
C# 解决窗体闪烁
查看>>
CSS魔法堂:Transition就这么好玩
查看>>
【OpenStack】network相关知识学习
查看>>
centos 7下独立的python 2.7环境安装
查看>>
[日常] 算法-单链表的创建
查看>>
前端工程化系列[01]-Bower包管理工具的使用
查看>>
使用 maven 自动将源码打包并发布
查看>>
Spark:求出分组内的TopN
查看>>
Python爬取豆瓣《复仇者联盟3》评论并生成乖萌的格鲁特
查看>>
关于跨DB增量(增、改)同步两张表的数据小技巧
查看>>
飞秋无法显示局域网好友
查看>>
学员会诊之03:你那惨不忍睹的三层架构
查看>>
vue-04-组件
查看>>
Golang协程与通道整理
查看>>
解决win7远程桌面连接时发生身份验证错误的方法
查看>>