I need to replace a file with another one on a VFS (having both struct file) in a Linux kernel module. I tried 2 ways of doing that but both have some problems.So I have 2 files correctly initialized, the first solution was:
vfs_truncate(&filp_one->f_path, 0);err = vfs_copy_file_range(filp_two, 0, filp_one, 0, file_size, 0);
where file_size is the size of filp_two, I need the truncate because if the size of filp_one is bigger than filp_two I could have a dirty copy.In this case, the problem is that another process can modify the file between the two operations and if I try to lock with:
inode_lock(filp_one->f_inode);vfs_truncate(&filp_one->f_path, 0);err = vfs_copy_file_range(filp_two, 0, filp_one, 0, file_size, 0); inode_unlock(filp_one->f_inode);
the result is a deadlock.
The other solution and maybe better I thought was to rename filp_two and then unlink.
vfs_rename(parent, filp_two_dentry , parent, filp_one_dentry, NULL, RENAME_WHITEOUT);
I also locked with rename_lock, but I omitted because that's not the point.In this case, the problem is that all the other open file structs after one rename will return an error "already freed". So I wanted to know if exists a way to update the file descriptors avoiding close and open again.Looking into the source I saw the d_move function d_move, so I added this line, but nothing changes:
d_exchange(filp_one_dentry, filp_two_dentry);
Thanks for your attention and sorry for my English
P.S. I know that is not preferable to work with files in this way