mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-19 10:44:14 +08: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
@ -389,6 +389,89 @@ static long ovl_compat_ioctl(struct file *file, unsigned int cmd,
|
|||||||
return ovl_ioctl(file, cmd, arg);
|
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 = {
|
const struct file_operations ovl_file_operations = {
|
||||||
.open = ovl_open,
|
.open = ovl_open,
|
||||||
.release = ovl_release,
|
.release = ovl_release,
|
||||||
@ -400,4 +483,8 @@ const struct file_operations ovl_file_operations = {
|
|||||||
.fallocate = ovl_fallocate,
|
.fallocate = ovl_fallocate,
|
||||||
.unlocked_ioctl = ovl_ioctl,
|
.unlocked_ioctl = ovl_ioctl,
|
||||||
.compat_ioctl = ovl_compat_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 New Issue
Block a user