共計(jì) 5738 個(gè)字符,預(yù)計(jì)需要花費(fèi) 15 分鐘才能閱讀完成。
這篇文章主要介紹 cephfs linux kernel client 針對 linux page cache 的操作代碼,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!
針對 linux page cache 的操作主要體現(xiàn)在 struct address_space_operations 數(shù)據(jù)結(jié)構(gòu)中,cephfs 處理 linux page cache 的函數(shù)集合如下:
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)
|__調(diào)用 readpage_nounlock(filep, page) 在加鎖的情況下讀取一個(gè)物理內(nèi)存頁的數(shù)據(jù)
|__確定 page 的 offset 沒有超出 inode 的總長度
|__調(diào)用 ceph_readpage_from_fscache() 函數(shù)嘗試從 fscache 中讀取一個(gè)物理內(nèi)存頁的數(shù)據(jù)
|__若讀取成功則直接返回
|__調(diào)用 ceph_osdc_readpages() 函數(shù)從 ceph 集群中讀取一個(gè)物理內(nèi)存頁的數(shù)據(jù)
|__調(diào)用 ceph_osdc_new_reqeust() 函數(shù)創(chuàng)建一個(gè)讀請求
|__調(diào)用 osd_req_op_extent_osd_data_pages() 函數(shù)為讀請求的返回內(nèi)容分配內(nèi)存空間
|__調(diào)用 ceph_osdc_start_request() 函數(shù)將讀請求同步發(fā)送給 ceph 集群
|__調(diào)用 flush_dcache_page() 函數(shù)刷 page 到 dcache 中
|__調(diào)用 SetPageUptodate() 函數(shù)設(shè)置物理內(nèi)存頁的狀態(tài)是 update 的
|__調(diào)用 ceph_readpage_to_fscache() 函數(shù)將新讀到的物理內(nèi)存頁更新到 fscache 中
|__調(diào)用 unlock_page(page)
|__調(diào)用 clear_bit_unlock() 函數(shù)為 page 解鎖
|__調(diào)用 wake_up_page() 函數(shù)喚醒等待該 page 的相關(guān)進(jìn)程
ceph_readpages(struct file *file, struct address_space *mapping, struct list_head *page_list, unsigned nr_pages) 讀取多個(gè)頁
|__調(diào)用 ceph_readpages_from_fscache() 函數(shù)嘗試從 fscache 中讀取多個(gè)物理內(nèi)存頁的數(shù)據(jù)
|__若讀取成功則直接返回
|__遍歷 page_list
|__調(diào)用 start_read() 函數(shù)讀取數(shù)據(jù)到 page_list 所包含的物理內(nèi)存頁
|__調(diào)用 ceph_osdc_new_reqeust() 函數(shù)創(chuàng)建一個(gè)讀請求
|__調(diào)用 calc_pages_for(0, len) 函數(shù)得到讀取指定長度 len 的數(shù)據(jù)需要的物理內(nèi)存頁數(shù)
|__從 page_list 中摘下指定數(shù)量的物理內(nèi)存頁
|__調(diào)用 osd_req_op_extent_osd_data_pages() 函數(shù)將從 page_list 中摘下的物理內(nèi)存頁作為讀請求的接收緩沖
|__設(shè)置讀請求完成后的回調(diào)函數(shù)為 finish_read()
|__調(diào)用 ceph_osdc_start_request() 函數(shù)將讀請求同步發(fā)送給 ceph 集群
finish_read(struct ceph_osd_request *req) 從 ceph 集群中讀操作結(jié)束后的回調(diào)函數(shù)
|__遍歷讀取到的所有物理內(nèi)存頁
|__調(diào)用 flush_dcache_page() 函數(shù)將 page 中的內(nèi)存刷到 dcache 中
|__調(diào)用 SetPageUptodate() 函數(shù)設(shè)置 page 的狀態(tài)是 uptodate 的
|__調(diào)用 ceph_readpage_to_fscache() 函數(shù)將讀取到的 page 內(nèi)存同步到 fscache 中
ceph_writepage(struct page *page, struct writeback_control *wbc)
|__調(diào)用 writepage_nounlock(page,wbc) 函數(shù)同步 page 信息到 ceph 集群
|__調(diào)用 page_snap_context() 函數(shù)得到 page 的 snap context 信息 (page 將 CephSnapContext 信息寫入到 page 的 private 中)
|__調(diào)用 set_page_writeback(page) 函數(shù)設(shè)置 page writeback 標(biāo)識
|__調(diào)用 ceph_osdc_writepages() 函數(shù)將 page 信息同步寫到 ceph 集群
|__調(diào)用 ceph_osdc_new_reqeust() 函數(shù)創(chuàng)建一個(gè)寫請求
|__調(diào)用 osd_req_op_extent_osd_data_pages() 函數(shù)為寫請求設(shè)置寫內(nèi)容物理內(nèi)存頁
|__調(diào)用 ceph_osdc_start_request() 函數(shù)將寫請求同步發(fā)送給 ceph 集群
|__設(shè)置 page- private=0,即:刪除 page 的 CephSnapContext 信息
|__調(diào)用 ClearPagePrivate(page) 函數(shù)清空 page 的 private
|__調(diào)用 end_page_writeback() 函數(shù)
|__調(diào)用 wake_up_page(page, PG_writeback) 函數(shù)喚醒在 page 上等待 writeback 完成的進(jìn)程
ceph_writepages_start(struct address_space *mapping, struct writeback_control *wbc)
|__調(diào)用 pagevec_init(pvec, 0) 函數(shù)初始化 struct pagevec 實(shí)例 pvec
|__從 wbc 的 range_start 和 range_end 中得到 start 和 end
|__調(diào)用 pagevec_lookup_tag(pvec, mapping, PAGECACHE_TAG_DIRTY…) 函數(shù)從 mapping 中 radix tree 中找到 tags==PAGECACHE_TAG_DIRTY 的所有 pages 且將所有 pages 寫入到 pvec 中
|__遍歷所有 PAGECACHE_TAG_DIRTY 的 pages
|__調(diào)用 page_offset() 函數(shù)得到 page 所在的 offset 值
|__調(diào)用 ceph_calc_file_object_mapping() 函數(shù)得到從 offset 開始,長度是 len 的文件所占用的 objects 個(gè)數(shù)以及在 object 中的偏移
|__將 page 添加到 pages 數(shù)組中
|__從 pages 數(shù)組中得到 offset 值,即:offset=page_offset(pages[0])
|__調(diào)用 ceph_osdc_new_request() 函數(shù)創(chuàng)建一個(gè)寫數(shù)據(jù)請求
|__設(shè)置寫數(shù)據(jù)請求的回調(diào)函數(shù)為 writepages_finish
|__調(diào)用 osd_req_op_extent_osd_data_pages() 函數(shù)添加寫請求額外的數(shù)據(jù)
|__調(diào)用 ceph_osdc_start_request() 函數(shù)將寫請求同步發(fā)送到 ceph 集群
writepages_finish(struct ceph_osd_request *req)
|__清除所有在發(fā)送寫請求過程中產(chǎn)生的內(nèi)存
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
|__調(diào)用 grab_cache_page_write_begin(mapping, index, flags) 函數(shù)在 pagecache 中指定位置 index 出獲取或創(chuàng)建一個(gè)物理內(nèi)存頁 page
|__調(diào)用 pagecache_get_page() 函數(shù)在 pagecache 中指定位置 index 出獲取或創(chuàng)建一個(gè)物理內(nèi)存頁 page
|__調(diào)用 wait_for_stable_page(page) 函數(shù)等待該 page 上的 writeback 函數(shù)返回
|__調(diào)用 ceph_update_writeable_page(file, pos, len, page) 函數(shù)只允許往 clean page 里寫入數(shù)據(jù)或者已經(jīng) dirty 的 snap context 里寫入數(shù)據(jù)
|__調(diào)用 wait_on_page_writeback(page) 函數(shù)等待 page 的 writeback 完成
|__調(diào)用 page_snap_context(page) 函數(shù)得到該 page 的 snap context
|__若 snap context 的 seq oldest- seq
|__調(diào)用 ceph_queue_writeback(inode) 函數(shù)將 inode 放入到 writeback 隊(duì)列中
|__調(diào)用 clear_page_dirty_for_io(page) 函數(shù)清除 page 上的 dirty 標(biāo)識
|__調(diào)用 writepage_nounlock(page, NULL) 函數(shù)將 page 數(shù)據(jù)同步的寫入到 ceph 集群
|__調(diào)用 PageUptodate(page) 檢查 page 是否是 uptodate 的
|__是則直接返回
|__若 page 已經(jīng)滿了
|__直接返回
|__調(diào)用 i_size_read(inode) 函數(shù)得到 inode 的讀數(shù)據(jù)的大小
|__調(diào)用 readpage_nounlock(file, page) 函數(shù)從 ceph 集群中讀取數(shù)據(jù)到 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
|__調(diào)用 zero_user_segment(page, from+copied, len) 函數(shù)將 page 中從 from+copied 一直到 from+copied+len 的內(nèi)存空間置 0
|__若 pos+copied i_size_read(inode)
|__調(diào)用 ceph_inode_set_size() 函數(shù)設(shè)置 inode 的 size 為 pos+copied
|__若 Page 不是 uptodate 的
|__調(diào)用 SetPageUptodate(page) 函數(shù)設(shè)置 page 是 uptodate 的
|__調(diào)用 set_page_dirty(page) 函數(shù)設(shè)置 page 是 dirty 的
ceph_set_page_dirty(struct page *page)
|__若 PageDirty(page)
|__直接返回
|__通過 mapping 的到 struct ceph_inode_info 結(jié)構(gòu)
|__調(diào)用__ceph_have_pending_cap_snap() 函數(shù)檢查 cephfs 是否有 snaps
|__從 struct ceph_inode_info 結(jié)構(gòu)中的 i_cap_snaps 列表中得到 struct ceph_cap_snap 結(jié)構(gòu)
|__從 struct ceph_cap_snap 結(jié)構(gòu)中得到 struct ceph_snap_context 結(jié)構(gòu)
|__若 cephfs 沒有 snaps
|__調(diào)用 ceph_get_snap_context() 函數(shù)從 struct ceph_inode_info 的 i_head_spapc 中得到 struct ceph_snap_context 結(jié)構(gòu)
|__將 struct ceph_snap_context 結(jié)構(gòu)設(shè)置到 page 的 private 中,即:page- private=snapc
|__調(diào)用__set_page_dirty_nobuffers() 函數(shù)將 page 在 address_spaces 中的 radix tree 中設(shè)置成 dirty
ceph_invalidatepage(struct page *page, unsigned int offset, unsigned int length)
|__調(diào)用 ceph_invalidate_fscache_page() 函數(shù)使得 page 在 fscache 中無效
|__若 page 沒有 private
|__直接返回
|__設(shè)置 page- private= 0 清除 page 的 snaps
|__調(diào)用 ClearPagePriavte(page)
ceph_releasepage(struct page *page, gfp_t g)
|__調(diào)用 ceph_release_fscache_page() 函數(shù)在 fscache 中刪除 page
|__返回!PagePrivate(page)
ceph_direct_io(struct kiocb *iocb, struct iov_iter *iter)
|__返回 -EINVAL
以上是“cephfs linux kernel client 針對 linux page cache 的操作代碼”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注丸趣 TV 行業(yè)資訊頻道!