f2fs文件系统的页缓存
生活随笔
收集整理的這篇文章主要介紹了
f2fs文件系统的页缓存
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
f2fs有三種inode,meta_inode,node_inode和普通的文件inode,前兩種inode只存在于vfs層,且數量只有一個。meta_inode對應于SIT,NAT,SSA,checkpoint和super block這些文件系統元數據,node inode對應于main area的node segment的數據,普通文件inode讀寫的區域對應于main area的data segment。所以,所有的f2fs數據的讀寫都是通過vfs層的inode的。這些inode的保存在f2fs_sb_info中,在文件系統初始化時f2fs_fill_super生成。再看inode的初始化過程,在函數inode.c/f2fs_iget中:
struct inode *f2fs_iget(struct super_block *sb, unsigned long ino) {struct f2fs_sb_info *sbi = F2FS_SB(sb);struct inode *inode;int ret = 0;inode = iget_locked(sb, ino);if (!inode)return ERR_PTR(-ENOMEM);if (!(inode->i_state & I_NEW)) {trace_f2fs_iget(inode);return inode;}if (ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi))goto make_now;ret = do_read_inode(inode);if (ret)goto bad_inode; make_now:if (ino == F2FS_NODE_INO(sbi)) {inode->i_mapping->a_ops = &f2fs_node_aops;mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);} else if (ino == F2FS_META_INO(sbi)) {inode->i_mapping->a_ops = &f2fs_meta_aops;mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);} else if (S_ISREG(inode->i_mode)) {inode->i_op = &f2fs_file_inode_operations;inode->i_fop = &f2fs_file_operations;inode->i_mapping->a_ops = &f2fs_dblock_aops;} else if (S_ISDIR(inode->i_mode)) {inode->i_op = &f2fs_dir_inode_operations;inode->i_fop = &f2fs_dir_operations;inode->i_mapping->a_ops = &f2fs_dblock_aops;mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO);} else if (S_ISLNK(inode->i_mode)) {inode->i_op = &f2fs_symlink_inode_operations;inode->i_mapping->a_ops = &f2fs_dblock_aops;} else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) ||S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {inode->i_op = &f2fs_special_inode_operations;init_special_inode(inode, inode->i_mode, inode->i_rdev);} else {ret = -EIO;goto bad_inode;}unlock_new_inode(inode);trace_f2fs_iget(inode);return inode;bad_inode:iget_failed(inode);trace_f2fs_iget_exit(inode, ret);return ERR_PTR(ret); }初始化過程區別對待了meta_inode和node_inode,再看看它們的address_space_operation:const struct address_space_operations f2fs_node_aops = {.writepage = f2fs_write_node_page,.writepages = f2fs_write_node_pages,.set_page_dirty = f2fs_set_node_page_dirty,.invalidatepage = f2fs_invalidate_node_page,.releasepage = f2fs_release_node_page, }; const struct address_space_operations f2fs_meta_aops = {.writepage = f2fs_write_meta_page,.writepages = f2fs_write_meta_pages,.set_page_dirty = f2fs_set_meta_page_dirty, }; 也許大家會覺得奇怪,為什么只有writepage而沒有readpage呢,那它們是怎么讀磁盤上的數據呢?文件系統實現了兩個函數node.c/get_node_page和checkpoint.c/get_meta_page,這兩個函數的流程類似,都是首先使用grab_cache_page去獲取特定位置的頁,grab_cache_page首先會查找address_space的基數樹,如果找到該頁則返回,如果找不到,則從伙伴系統分配一個新的頁;然后調用f2fs_readpage讀取磁盤上該頁的內容。 struct page *get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index) {struct address_space *mapping = sbi->meta_inode->i_mapping;struct page *page; repeat:page = grab_cache_page(mapping, index);if (!page) {cond_resched();goto repeat;}if (PageUptodate(page))goto out;if (f2fs_readpage(sbi, page, index, READ_SYNC))goto repeat;lock_page(page);if (page->mapping != mapping) {f2fs_put_page(page, 1);goto repeat;} out:mark_page_accessed(page);return page; } get_meta_page的參數index,直接對應了該頁在磁盤上的塊地址,所以可以直接作為f2fs_readpage的參數。以讀取SSA的一個實例看,如功能函數get_sum_page,該函數實現很簡單,通過GET_SUM_BLOCK(sbi, segno)獲取summary page的塊地址,該宏展開為 #define GET_SUM_BLOCK(sbi, segno) \((sbi->sm_info->ssa_blkaddr) + segno) sbi->sm_info->ssa_blkaddr是SSA區域的起始地址,segno是segment number,由于一個segment的summary存儲在一個page上,因此直接相加就是塊地址。 struct page *get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno) {return get_meta_page(sbi, GET_SUM_BLOCK(sbi, segno)); } 而get_node_page稍稍有點不同: struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid) {struct address_space *mapping = sbi->node_inode->i_mapping;struct page *page;int err; repeat:page = grab_cache_page(mapping, nid);if (!page)return ERR_PTR(-ENOMEM);err = read_node_page(page, READ_SYNC);if (err < 0)return ERR_PTR(err);else if (err == LOCKED_PAGE)goto got_it;lock_page(page);if (!PageUptodate(page)) {f2fs_put_page(page, 1);return ERR_PTR(-EIO);}if (page->mapping != mapping) {f2fs_put_page(page, 1);goto repeat;} got_it:BUG_ON(nid != nid_of_node(page));mark_page_accessed(page);return page; }該函數的參數是node的number,在f2fs中,node number的實際塊地址在NAT中存儲,因此還需要讀取NAT的數據,獲得該node的塊地址,這些工作在read_node_page中完成。
總的來說,f2fs通過這三種inode把它的全部數據都管理起來,不得不說這是非常巧妙的設計啊
總結
以上是生活随笔為你收集整理的f2fs文件系统的页缓存的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 伽辽金法
- 下一篇: java信息管理系统总结_java实现科