F2FS源码分析-6.6 [其他重要数据结构以及函数] F2FS的重命名过程-f2fs_rename函数
生活随笔
收集整理的這篇文章主要介紹了
F2FS源码分析-6.6 [其他重要数据结构以及函数] F2FS的重命名过程-f2fs_rename函数
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
F2FS源碼分析系列文章
主目錄
一、文件系統(tǒng)布局以及元數(shù)據(jù)結(jié)構(gòu)
二、文件數(shù)據(jù)的存儲(chǔ)以及讀寫
三、文件與目錄的創(chuàng)建以及刪除(未完成)
四、垃圾回收機(jī)制
五、數(shù)據(jù)恢復(fù)機(jī)制
六、重要數(shù)據(jù)結(jié)構(gòu)或者函數(shù)的分析
F2FS的rename流程
rename流程介紹
sys_rename函數(shù)
sys_rename函數(shù)是一個(gè)系統(tǒng)調(diào)用,是rename函數(shù)進(jìn)入內(nèi)核層的第一個(gè)函數(shù):
SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newname) {// AT_FDCWD表示以相對(duì)路徑的方法找oldname和newname這個(gè)文件,flags=0return do_renameat2(AT_FDCWD, oldname, AT_FDCWD, newname, 0); }do_renameat2函數(shù)
do_renameat2函數(shù)比較長(zhǎng),考慮多個(gè)輸入flag的作用,這里只考慮sys_rename函數(shù)rename一個(gè)文件的情形,即flag=0,并以此精簡(jiǎn)函數(shù)。
static int do_renameat2(int olddfd, const char __user *oldname, int newdfd,const char __user *newname, unsigned int flags) {struct dentry *old_dentry, *new_dentry;struct dentry *trap;struct path old_path, new_path;struct qstr old_last, new_last;int old_type, new_type;struct inode *delegated_inode = NULL;struct filename *from;struct filename *to;unsigned int lookup_flags = 0, target_flags = LOOKUP_RENAME_TARGET;bool should_retry = false;int error;retry:// 接下來(lái)兩個(gè)函數(shù)最重要的作用是根據(jù)oldname和newname找到父目錄的dentry結(jié)構(gòu)// 這兩個(gè)dentry結(jié)構(gòu)保存在old_path和new_path中(注意是父目錄的dentry)from = filename_parentat(olddfd, getname(oldname), lookup_flags,&old_path, &old_last, &old_type);to = filename_parentat(newdfd, getname(newname), lookup_flags,&new_path, &new_last, &new_type);retry_deleg:// 這個(gè)函數(shù)會(huì)觸發(fā)一個(gè)全局的rename的互斥鎖,然后鎖兩個(gè)父目錄inode結(jié)構(gòu)trap = lock_rename(new_path.dentry, old_path.dentry);// 根據(jù)old path的父目錄找到需要被rename的文件的dentryold_dentry = __lookup_hash(&old_last, old_path.dentry, lookup_flags);// 根據(jù)new path的父目錄找到或創(chuàng)建新的dentrynew_dentry = __lookup_hash(&new_last, new_path.dentry, lookup_flags | target_flags);// 調(diào)用vfs_rename函數(shù)進(jìn)行重命名// 傳入的是新舊兩個(gè)目錄的inode,以及需要重命名的兩個(gè)dentry, flags = 0error = vfs_rename(old_path.dentry->d_inode, old_dentry,new_path.dentry->d_inode, new_dentry,&delegated_inode, flags);dput(new_dentry);dput(old_dentry);// 解鎖全局rename互斥鎖,釋放兩個(gè)inode鎖unlock_rename(new_path.dentry, old_path.dentry);path_put(&new_path);putname(to);path_put(&old_path);putname(from); exit:return error; }vfs_rename函數(shù)
vfs_rename函數(shù)也會(huì)做簡(jiǎn)化,簡(jiǎn)化的情形是將文件A重命名到文件B (B可能已經(jīng)存在,或者不存在),flags=0。
int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,struct inode *new_dir, struct dentry *new_dentry,struct inode **delegated_inode, unsigned int flags) {int error;bool is_dir = d_is_dir(old_dentry);struct inode *source = old_dentry->d_inode; // 舊文件inodestruct inode *target = new_dentry->d_inode; // 新文件inodebool new_is_dir = false;unsigned max_links = new_dir->i_sb->s_max_links;struct name_snapshot old_name;dget(new_dentry); // 對(duì)新文件的引用計(jì)數(shù)+1if (target)inode_lock(target); // 如果新文件已經(jīng)存在,則上鎖error = old_dir->i_op->rename(old_dir, old_dentry,new_dir, new_dentry, flags);out:if (target)inode_unlock(target); // 如果新文件已經(jīng)存在,則解鎖dput(new_dentry); // 對(duì)新文件的引用計(jì)數(shù)-1return error; }f2fs_rename函數(shù)
f2fs_rename函數(shù)也會(huì)做簡(jiǎn)化,簡(jiǎn)化的情形是將文件A重命名到文件B (B可能已經(jīng)存在,或者不存在),flags=0。
static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,struct inode *new_dir, struct dentry *new_dentry,unsigned int flags) {struct f2fs_sb_info *sbi = F2FS_I_SB(old_dir);struct inode *old_inode = d_inode(old_dentry);struct inode *new_inode = d_inode(new_dentry);struct inode *whiteout = NULL;struct page *old_dir_page;struct page *old_page, *new_page = NULL;struct f2fs_dir_entry *old_dir_entry = NULL;struct f2fs_dir_entry *old_entry;struct f2fs_dir_entry *new_entry;bool is_old_inline = f2fs_has_inline_dentry(old_dir);int err;// 輸入顯然是// 舊的父目錄old_dir,舊的文件old_dentry// 新的父目錄new_dir,新的文件new_dentry// 根據(jù)舊文件的名字找到對(duì)應(yīng)的f2fs_dir_entry,old_page保存的是磁盤上的dir_entry數(shù)據(jù)old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);if (new_inode) { // 如果新文件已經(jīng)存在// 根據(jù)新文件的名字找到對(duì)應(yīng)的f2fs_dir_entry,new_page保存的是磁盤上的數(shù)據(jù)new_entry = f2fs_find_entry(new_dir, &new_dentry->d_name,&new_page);// F2FS獲取一個(gè)全局讀信號(hào)量f2fs_lock_op(sbi);// 在管理orphan inode的全局結(jié)構(gòu)中,將orphan inode的數(shù)目+1。err = f2fs_acquire_orphan_inode(sbi);// 這里進(jìn)行新舊inode的link的變化:// 將new_dentry所屬的inode指向old_inode// 因?yàn)閞ename的時(shí)候新inode是已經(jīng)存在了,因此rename的操作就是將// 新路徑原來(lái)的inode無(wú)效掉,然后替換為舊路徑的inodef2fs_set_link(new_dir, new_entry, new_page, old_inode);new_inode->i_ctime = current_time(new_inode);down_write(&F2FS_I(new_inode)->i_sem); // 拿寫信號(hào)量// 減少新inode一個(gè)引用計(jì)數(shù),因?yàn)楸籸ename了f2fs_i_links_write(new_inode, false);up_write(&F2FS_I(new_inode)->i_sem); // 釋放寫信號(hào)量// 如果引用計(jì)數(shù)下降到0,則添加到orphan inode中,在checkpoint管理if (!new_inode->i_nlink)f2fs_add_orphan_inode(new_inode);elsef2fs_release_orphan_inode(sbi); // 否則管理結(jié)構(gòu)將orphan inode的數(shù)目-1。} else {// 這個(gè)情況是新路徑的Inode不存在// F2FS獲取一個(gè)全局讀信號(hào)量f2fs_lock_op(sbi);// 由于新inode是不存在的,因此直接將舊inode添加到新的f2fs_dir_entry中err = f2fs_add_link(new_dentry, old_inode);}down_write(&F2FS_I(old_inode)->i_sem);if (!old_dir_entry || whiteout)file_lost_pino(old_inode); // 這個(gè)操作要保留著用于數(shù)據(jù)恢復(fù)elseF2FS_I(old_inode)->i_pino = new_dir->i_ino;up_write(&F2FS_I(old_inode)->i_sem);old_inode->i_ctime = current_time(old_inode);f2fs_mark_inode_dirty_sync(old_inode, false);// 新的數(shù)據(jù)已經(jīng)加入到新的f2fs_dir_entry,因此舊entry就去去除掉f2fs_delete_entry(old_entry, old_page, old_dir, NULL);// F2FS釋放全局讀信號(hào)量f2fs_unlock_op(sbi);f2fs_update_time(sbi, REQ_TIME);return 0; }總結(jié)
以上是生活随笔為你收集整理的F2FS源码分析-6.6 [其他重要数据结构以及函数] F2FS的重命名过程-f2fs_rename函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 图像调整亮度饱和度 c语言,数据增强-亮
- 下一篇: CISCO CCNA CCNP CCIE