mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	ovl: add reflink/copyfile/dedup support
Since set of arguments are so similar, handle in a common helper. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
		
							parent
							
								
									f7c72396d0
								
							
						
					
					
						commit
						8ede205541
					
				
					 1 changed files with 87 additions and 0 deletions
				
			
		|  | @ -389,6 +389,89 @@ static long ovl_compat_ioctl(struct file *file, unsigned int cmd, | |||
| 	return ovl_ioctl(file, cmd, arg); | ||||
| } | ||||
| 
 | ||||
| enum ovl_copyop { | ||||
| 	OVL_COPY, | ||||
| 	OVL_CLONE, | ||||
| 	OVL_DEDUPE, | ||||
| }; | ||||
| 
 | ||||
| static ssize_t ovl_copyfile(struct file *file_in, loff_t pos_in, | ||||
| 			    struct file *file_out, loff_t pos_out, | ||||
| 			    u64 len, unsigned int flags, enum ovl_copyop op) | ||||
| { | ||||
| 	struct inode *inode_out = file_inode(file_out); | ||||
| 	struct fd real_in, real_out; | ||||
| 	const struct cred *old_cred; | ||||
| 	ssize_t ret; | ||||
| 
 | ||||
| 	ret = ovl_real_fdget(file_out, &real_out); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	ret = ovl_real_fdget(file_in, &real_in); | ||||
| 	if (ret) { | ||||
| 		fdput(real_out); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	old_cred = ovl_override_creds(file_inode(file_out)->i_sb); | ||||
| 	switch (op) { | ||||
| 	case OVL_COPY: | ||||
| 		ret = vfs_copy_file_range(real_in.file, pos_in, | ||||
| 					  real_out.file, pos_out, len, flags); | ||||
| 		break; | ||||
| 
 | ||||
| 	case OVL_CLONE: | ||||
| 		ret = vfs_clone_file_range(real_in.file, pos_in, | ||||
| 					   real_out.file, pos_out, len); | ||||
| 		break; | ||||
| 
 | ||||
| 	case OVL_DEDUPE: | ||||
| 		ret = vfs_dedupe_file_range_one(real_in.file, pos_in, | ||||
| 						real_out.file, pos_out, len); | ||||
| 		break; | ||||
| 	} | ||||
| 	revert_creds(old_cred); | ||||
| 
 | ||||
| 	/* Update size */ | ||||
| 	ovl_copyattr(ovl_inode_real(inode_out), inode_out); | ||||
| 
 | ||||
| 	fdput(real_in); | ||||
| 	fdput(real_out); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static ssize_t ovl_copy_file_range(struct file *file_in, loff_t pos_in, | ||||
| 				   struct file *file_out, loff_t pos_out, | ||||
| 				   size_t len, unsigned int flags) | ||||
| { | ||||
| 	return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, flags, | ||||
| 			    OVL_COPY); | ||||
| } | ||||
| 
 | ||||
| static int ovl_clone_file_range(struct file *file_in, loff_t pos_in, | ||||
| 				struct file *file_out, loff_t pos_out, u64 len) | ||||
| { | ||||
| 	return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, 0, | ||||
| 			    OVL_CLONE); | ||||
| } | ||||
| 
 | ||||
| static int ovl_dedupe_file_range(struct file *file_in, loff_t pos_in, | ||||
| 				 struct file *file_out, loff_t pos_out, u64 len) | ||||
| { | ||||
| 	/*
 | ||||
| 	 * Don't copy up because of a dedupe request, this wouldn't make sense | ||||
| 	 * most of the time (data would be duplicated instead of deduplicated). | ||||
| 	 */ | ||||
| 	if (!ovl_inode_upper(file_inode(file_in)) || | ||||
| 	    !ovl_inode_upper(file_inode(file_out))) | ||||
| 		return -EPERM; | ||||
| 
 | ||||
| 	return ovl_copyfile(file_in, pos_in, file_out, pos_out, len, 0, | ||||
| 			    OVL_DEDUPE); | ||||
| } | ||||
| 
 | ||||
| const struct file_operations ovl_file_operations = { | ||||
| 	.open		= ovl_open, | ||||
| 	.release	= ovl_release, | ||||
|  | @ -400,4 +483,8 @@ const struct file_operations ovl_file_operations = { | |||
| 	.fallocate	= ovl_fallocate, | ||||
| 	.unlocked_ioctl	= ovl_ioctl, | ||||
| 	.compat_ioctl	= ovl_compat_ioctl, | ||||
| 
 | ||||
| 	.copy_file_range	= ovl_copy_file_range, | ||||
| 	.clone_file_range	= ovl_clone_file_range, | ||||
| 	.dedupe_file_range	= ovl_dedupe_file_range, | ||||
| }; | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Miklos Szeredi
						Miklos Szeredi