前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >探究ext4文件系统中的rename

探究ext4文件系统中的rename

作者头像
用户4700054
发布2022-08-17 12:49:39
1K0
发布2022-08-17 12:49:39
举报
文章被收录于专栏:存储内核技术交流
试验环境
  • rename测试代码
代码语言:javascript
复制
package main  
  
import (  
   "flag"  
 "fmt" "os")  
  
var (  
   oldName = flag.String("o","src_name","default source file name")  
   newName = flag.String("n","dst_name","default dst file name")  
)  
func main() {  
   flag.Parse()  
   if err := os.Rename(*oldName,*newName);err != nil {  
      fmt.Println("rename failed:",err)  
      return  
 }  
   fmt.Println("rename succ")  
  
}
  • rename测试过程
代码语言:javascript
复制
$ cp ~/1.go  a_file
$ cp ~/1.go  b_file
// a_file inode= 167996098
// b_file inode= 167996099
$ ls -i
167996098 a_file  167996099 b_file  268630153 rename_file
$ ./rename_file  -o a_file  -n b_file 
rename succ

// rename完成后,b_file的inode就是a_file的inode
$ ls -i
167996098 b_file  268630153 rename_file
结论
  • rename的posix语义是原子语义,要么成功要么失败;
  • rename的新文件从试验的过程中可以看出,old_name对应的文件的inode就是new_name对应文件的inode,new_name的文件在操作完成后被删删除。
  • rename过程是记录rename过程的日志,然后删除new_name对应inode和old_name对用的dentry.接着更新new_name对应的dentry中的inode为old_name的inode
分析
代码语言:javascript
复制
// 这里分析的是ext4本地文件系统,

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)
{
	struct inode *source = old_dentry->d_inode;
	struct inode *target = new_dentry->d_inode;
	if (source == target)
		return 0;

	// 如果target的dentry dcache不存在,则创建
	if (!target) {
		error = may_create(new_dir, new_dentry);
	} else {
	// 否则就删除dcache dentry
		new_is_dir = d_is_dir(new_dentry);

		if (!(flags & RENAME_EXCHANGE))
			error = may_delete(new_dir, new_dentry, is_dir);
		else
			error = may_delete(new_dir, new_dentry, new_is_dir);
	}

	// 最后调用具体ext4文件系统的rename函数
	error = old_dir->i_op->rename(old_dir, old_dentry,
				       new_dir, new_dentry, flags);
}



// 保留大体的流程的ext4_rename的函数
static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
		       struct inode *new_dir, struct dentry *new_dentry,
		       unsigned int flags)
{
	handle_t *handle = NULL;
	struct ext4_renament old = {
		.dir = old_dir,
		.dentry = old_dentry,
		.inode = d_inode(old_dentry),
	};
	struct ext4_renament new = {
		.dir = new_dir,
		.dentry = new_dentry,
		.inode = d_inode(new_dentry),
	};

	// 查找dcache的entry,并释放旧文件的entry
	old.bh = ext4_find_entry(old.dir, &old.dentry->d_name, &old.de, NULL);
	if (IS_ERR(old.bh))
		return PTR_ERR(old.bh);


	// 开始记录rename的日志
	handle = ext4_journal_start(old.dir, EXT4_HT_DIR, credits);


	// 如果new_name的文件不存在,则old_name的inode设置到新的dentry中
	if (!new.bh) {
		retval = ext4_add_entry(handle, new.dentry, old.inode);
		if (retval)
			goto end_rename;
	} else {
	// new_name文件存在,设置new_name中的inode为就文件的inode
		retval = ext4_setent(handle, &new,
				     old.inode->i_ino, old_file_type);
	
	}

	// 释放rename过程中临时构造的ext4_renament
	ext4_rename_delete(handle, &old, force_reread);

	// 日志记录结束
	ext4_journal_stop(handle);
}


// dir inode的操作函数
const struct inode_operations ext4_dir_inode_operations = {
	.create		= ext4_create,
	.lookup		= ext4_lookup,
	.link		= ext4_link,
	.unlink		= ext4_unlink,
	.symlink	= ext4_symlink,
	.mkdir		= ext4_mkdir,
	.rmdir		= ext4_rmdir,
	.mknod		= ext4_mknod,
	.tmpfile	= ext4_tmpfile,
	.rename		= ext4_rename2,
	.setattr	= ext4_setattr,
	.getattr	= ext4_getattr,
	.listxattr	= ext4_listxattr,
	.get_acl	= ext4_get_acl,
	.set_acl	= ext4_set_acl,
	.fiemap         = ext4_fiemap,
};
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-02-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 存储内核技术交流 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 试验环境
  • 结论
  • 分析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档