共计 5738 个字符,预计需要花费 15 分钟才能阅读完成。
这篇文章主要介绍 cephfs linux kernel client 针对 linux page cache 的操作代码,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!
针对 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
以上是“cephfs linux kernel client 针对 linux page cache 的操作代码”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注丸趣 TV 行业资讯频道!