F2FS源码分析系列文章

主目录
一、文件系统布局以及元数据结构
二、文件数据的存储以及读写
三、文件与目录的创建以及删除(未完成)
四、垃圾回收机制
五、数据恢复机制
六、重要数据结构或者函数的分析
  1. f2fs_summary的作用
  2. f2fs_journal的作用
  3. f2fs_map_block的作用
  4. get_dnode_of_data的作用
  5. get_node_page的作用(未完成)

F2FS的rename流程

rename流程介绍

  1. sys_rename函数
  2. do_renameat2函数
  3. vfs_rename函数
  4. f2fs_rename函数

sys_rename函数

sys_rename函数是一个系统调用,是rename函数进入内核层的第一个函数:

SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newname)
{// AT_FDCWD表示以相对路径的方法找oldname和newname这个文件,flags=0return do_renameat2(AT_FDCWD, oldname, AT_FDCWD, newname, 0);
}

do_renameat2函数

do_renameat2函数比较长,考虑多个输入flag的作用,这里只考虑sys_rename函数rename一个文件的情形,即flag=0,并以此精简函数。

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:// 接下来两个函数最重要的作用是根据oldname和newname找到父目录的dentry结构// 这两个dentry结构保存在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:// 这个函数会触发一个全局的rename的互斥锁,然后锁两个父目录inode结构trap = lock_rename(new_path.dentry, old_path.dentry);// 根据old path的父目录找到需要被rename的文件的dentryold_dentry = __lookup_hash(&old_last, old_path.dentry, lookup_flags);// 根据new path的父目录找到或创建新的dentrynew_dentry = __lookup_hash(&new_last, new_path.dentry, lookup_flags | target_flags);// 调用vfs_rename函数进行重命名// 传入的是新旧两个目录的inode,以及需要重命名的两个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互斥锁,释放两个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函数

vfs_rename函数也会做简化,简化的情形是将文件A重命名到文件B (B可能已经存在,或者不存在),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); // 对新文件的引用计数+1if (target)inode_lock(target); // 如果新文件已经存在,则上锁error = old_dir->i_op->rename(old_dir, old_dentry,new_dir, new_dentry, flags);out:if (target)inode_unlock(target); // 如果新文件已经存在,则解锁dput(new_dentry); // 对新文件的引用计数-1return error;
}

f2fs_rename函数

f2fs_rename函数也会做简化,简化的情形是将文件A重命名到文件B (B可能已经存在,或者不存在),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// 根据旧文件的名字找到对应的f2fs_dir_entry,old_page保存的是磁盘上的dir_entry数据old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page);if (new_inode) { // 如果新文件已经存在// 根据新文件的名字找到对应的f2fs_dir_entry,new_page保存的是磁盘上的数据new_entry = f2fs_find_entry(new_dir, &new_dentry->d_name,&new_page);// F2FS获取一个全局读信号量f2fs_lock_op(sbi);// 在管理orphan inode的全局结构中,将orphan inode的数目+1。err = f2fs_acquire_orphan_inode(sbi);// 这里进行新旧inode的link的变化:// 将new_dentry所属的inode指向old_inode// 因为rename的时候新inode是已经存在了,因此rename的操作就是将// 新路径原来的inode无效掉,然后替换为旧路径的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); // 拿写信号量// 减少新inode一个引用计数,因为被rename了f2fs_i_links_write(new_inode, false);up_write(&F2FS_I(new_inode)->i_sem); // 释放写信号量// 如果引用计数下降到0,则添加到orphan inode中,在checkpoint管理if (!new_inode->i_nlink)f2fs_add_orphan_inode(new_inode);elsef2fs_release_orphan_inode(sbi); // 否则管理结构将orphan inode的数目-1。} else {// 这个情况是新路径的Inode不存在// F2FS获取一个全局读信号量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);  // 这个操作要保留着用于数据恢复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);// 新的数据已经加入到新的f2fs_dir_entry,因此旧entry就去去除掉f2fs_delete_entry(old_entry, old_page, old_dir, NULL);// F2FS释放全局读信号量f2fs_unlock_op(sbi);f2fs_update_time(sbi, REQ_TIME);return 0;
}

F2FS源码分析-6.6 [其他重要数据结构以及函数] F2FS的重命名过程-f2fs_rename函数相关推荐

  1. F2FS源码分析-1.4 [F2FS 元数据布局部分] Segment Infomation Table-SIT结构

    F2FS源码分析系列文章 主目录 一.文件系统布局以及元数据结构 总体结构 Superblock区域 Checkpoint区域 Segment Infomation Table区域(SIT) Node ...

  2. F2FS源码分析-1.6 [F2FS 元数据布局部分] Segment Summary Area-SSA结构

    F2FS源码分析系列文章 主目录 一.文件系统布局以及元数据结构 总体结构 Superblock区域 Checkpoint区域 Segment Infomation Table区域(SIT) Node ...

  3. F2FS源码分析-2.2 [F2FS 读写部分] F2FS的一般文件写流程分析

    F2FS源码分析系列文章 主目录 一.文件系统布局以及元数据结构 二.文件数据的存储以及读写 F2FS文件数据组织方式 一般文件写流程 一般文件读流程 目录文件读流程(未完成) 目录文件写流程(未完成 ...

  4. F2FS源码分析-2.3 [F2FS 读写部分] F2FS的一般文件读流程分析

    F2FS源码分析系列文章 主目录 一.文件系统布局以及元数据结构 二.文件数据的存储以及读写 F2FS文件数据组织方式 一般文件写流程 一般文件读流程 目录文件读流程(未完成) 目录文件写流程(未完成 ...

  5. F2FS源码分析-2.1 [F2FS 读写部分] F2FS文件数据组织方式以及物理地址的映射

    F2FS源码分析系列文章 主目录 一.文件系统布局以及元数据结构 二.文件数据的存储以及读写 F2FS文件数据组织方式 一般文件写流程 一般文件读流程 目录文件读流程(未完成) 目录文件写流程(未完成 ...

  6. F2FS源码分析-1.3 [F2FS 元数据布局部分] Checkpoint结构

    F2FS源码分析系列文章 主目录 一.文件系统布局以及元数据结构 总体结构 Superblock区域 Checkpoint区域 Segment Infomation Table区域(SIT) Node ...

  7. F2FS源码分析-1.2 [F2FS 元数据布局部分] Superblock结构

    F2FS源码分析系列文章 主目录 一.文件系统布局以及元数据结构 总体结构 Superblock区域 Checkpoint区域 Segment Infomation Table区域(SIT) Node ...

  8. F2FS源码分析-5.2 [数据恢复流程] 后滚恢复和Checkpoint的作用与实现

    F2FS源码分析系列文章 主目录 一.文件系统布局以及元数据结构 二.文件数据的存储以及读写 三.文件与目录的创建以及删除(未完成) 四.垃圾回收机制 五.数据恢复机制 数据恢复的原理以及方式 后滚恢 ...

  9. F2FS源码分析系列文章目录

    一.文件系统布局以及元数据结构 总体结构 Superblock区域 Checkpoint区域 Segment Infomation Table区域(SIT) Node Address Table区域( ...

最新文章

  1. Oslo团队研发首个形态自适应机器人 | AI日报
  2. spring_bean三种装配方式
  3. 《《python基础》》
  4. 【手写系列】透彻理解Spring事务设计思想之手写实现
  5. 1.3 Integer类详解
  6. 【十二省联考2019】皮配【分部dp】
  7. P1-0:项目框架搭建
  8. java pecs_Java 泛型: 什么是PECS(Producer Extends, Consumer Super)
  9. 苹果地图副总裁_苹果地图表现糟糕 iOS副总裁福斯特难辞其咎
  10. 跨链永续衍生品协议AntiMatter完成150万美元种子轮融资,NGC领投
  11. c++几个类互相包含
  12. 【CocoStudio游戏开发之一】制作多分辨率UI布局
  13. 网页版扫雷 -- React练习
  14. 如何把握银行信息科技风险管理的“度”?
  15. 工业控制网络通信协议概览 2020年7月27日
  16. 【EF】对象名 'dbo.EdmMetadata' 无效。
  17. scrapy爬虫入门
  18. 华为腾讯众安微众360大咖齐聚,2019中国区块链开发者大会等你来!
  19. error C1083:无法打开文件stddef.h或crtd bg.h
  20. IP协议的发展与演变

热门文章

  1. initial commit
  2. 刘润年度演讲2022:进化的力量(演讲全文)
  3. 网秦手机杀毒软件 v2.1 symbian uiq 是什么
  4. luogu 1558 色板游戏
  5. 汇编语言中逻辑运算符
  6. gorilla/mux 翻译
  7. mysql后门_运用Mysql语句生成后门具体办法
  8. 动态规划算法---求最长公共子序列
  9. 徒步旅行中的注意事项
  10. (原创)添加QQ好友日期爬虫01——总体思路