mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
Merge branch 'work.copy_file_range' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs copy_file_range updates from Al Viro: "Several series around copy_file_range/CLONE" * 'work.copy_file_range' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: btrfs: use new dedupe data function pointer vfs: hoist the btrfs deduplication ioctl to the vfs vfs: wire up compat ioctl for CLONE/CLONE_RANGE cifs: avoid unused variable and label nfsd: implement the NFSv4.2 CLONE operation nfsd: Pass filehandle to nfs4_preprocess_stateid_op() vfs: pull btrfs clone API to vfs layer locks: new locks_mandatory_area calling convention vfs: Add vfs_copy_file_range() support for pagecache copies btrfs: add .copy_file_range file operation x86: add sys_copy_file_range to syscall tables vfs: add copy_file_range syscall and vfs helper
This commit is contained in:
67
fs/ioctl.c
67
fs/ioctl.c
@@ -215,6 +215,29 @@ static int ioctl_fiemap(struct file *filp, unsigned long arg)
|
||||
return error;
|
||||
}
|
||||
|
||||
static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
|
||||
u64 off, u64 olen, u64 destoff)
|
||||
{
|
||||
struct fd src_file = fdget(srcfd);
|
||||
int ret;
|
||||
|
||||
if (!src_file.file)
|
||||
return -EBADF;
|
||||
ret = vfs_clone_file_range(src_file.file, off, dst_file, destoff, olen);
|
||||
fdput(src_file);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static long ioctl_file_clone_range(struct file *file, void __user *argp)
|
||||
{
|
||||
struct file_clone_range args;
|
||||
|
||||
if (copy_from_user(&args, argp, sizeof(args)))
|
||||
return -EFAULT;
|
||||
return ioctl_file_clone(file, args.src_fd, args.src_offset,
|
||||
args.src_length, args.dest_offset);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLOCK
|
||||
|
||||
static inline sector_t logical_to_blk(struct inode *inode, loff_t offset)
|
||||
@@ -545,6 +568,41 @@ static int ioctl_fsthaw(struct file *filp)
|
||||
return thaw_super(sb);
|
||||
}
|
||||
|
||||
static long ioctl_file_dedupe_range(struct file *file, void __user *arg)
|
||||
{
|
||||
struct file_dedupe_range __user *argp = arg;
|
||||
struct file_dedupe_range *same = NULL;
|
||||
int ret;
|
||||
unsigned long size;
|
||||
u16 count;
|
||||
|
||||
if (get_user(count, &argp->dest_count)) {
|
||||
ret = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
size = offsetof(struct file_dedupe_range __user, info[count]);
|
||||
|
||||
same = memdup_user(argp, size);
|
||||
if (IS_ERR(same)) {
|
||||
ret = PTR_ERR(same);
|
||||
same = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = vfs_dedupe_file_range(file, same);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = copy_to_user(argp, same, size);
|
||||
if (ret)
|
||||
ret = -EFAULT;
|
||||
|
||||
out:
|
||||
kfree(same);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* When you add any new common ioctls to the switches above and below
|
||||
* please update compat_sys_ioctl() too.
|
||||
@@ -600,6 +658,15 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
|
||||
case FIGETBSZ:
|
||||
return put_user(inode->i_sb->s_blocksize, argp);
|
||||
|
||||
case FICLONE:
|
||||
return ioctl_file_clone(filp, arg, 0, 0, 0);
|
||||
|
||||
case FICLONERANGE:
|
||||
return ioctl_file_clone_range(filp, argp);
|
||||
|
||||
case FIDEDUPERANGE:
|
||||
return ioctl_file_dedupe_range(filp, argp);
|
||||
|
||||
default:
|
||||
if (S_ISREG(inode->i_mode))
|
||||
error = file_ioctl(filp, cmd, arg);
|
||||
|
Reference in New Issue
Block a user