aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ioctl.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2015-12-03 06:59:50 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2015-12-07 23:11:33 -0500
commit04b38d601239b4d9be641b412cf4b7456a041c67 (patch)
tree196b5fa72848de2a98e09af86099d99da70f2833 /fs/ioctl.c
parentacc15575e78e534c12549d8057a692f490a50f61 (diff)
vfs: pull btrfs clone API to vfs layer
The btrfs clone ioctls are now adopted by other file systems, with NFS and CIFS already having support for them, and XFS being under active development. To avoid growth of various slightly incompatible implementations, add one to the VFS. Note that clones are different from file copies in several ways: - they are atomic vs other writers - they support whole file clones - they support 64-bit legth clones - they do not allow partial success (aka short writes) - clones are expected to be a fast metadata operation Because of that it would be rather cumbersome to try to piggyback them on top of the recent clone_file_range infrastructure. The converse isn't true and the clone_file_range system call could try clone file range as a first attempt to copy, something that further patches will enable. Based on earlier work from Peng Tao. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/ioctl.c')
-rw-r--r--fs/ioctl.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/fs/ioctl.c b/fs/ioctl.c
index 5d01d2638ca5..84c6e79829ab 100644
--- a/fs/ioctl.c
+++ b/fs/ioctl.c
@@ -215,6 +215,29 @@ static int ioctl_fiemap(struct file *filp, unsigned long arg)
215 return error; 215 return error;
216} 216}
217 217
218static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd,
219 u64 off, u64 olen, u64 destoff)
220{
221 struct fd src_file = fdget(srcfd);
222 int ret;
223
224 if (!src_file.file)
225 return -EBADF;
226 ret = vfs_clone_file_range(src_file.file, off, dst_file, destoff, olen);
227 fdput(src_file);
228 return ret;
229}
230
231static long ioctl_file_clone_range(struct file *file, void __user *argp)
232{
233 struct file_clone_range args;
234
235 if (copy_from_user(&args, argp, sizeof(args)))
236 return -EFAULT;
237 return ioctl_file_clone(file, args.src_fd, args.src_offset,
238 args.src_length, args.dest_offset);
239}
240
218#ifdef CONFIG_BLOCK 241#ifdef CONFIG_BLOCK
219 242
220static inline sector_t logical_to_blk(struct inode *inode, loff_t offset) 243static inline sector_t logical_to_blk(struct inode *inode, loff_t offset)
@@ -600,6 +623,12 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd,
600 case FIGETBSZ: 623 case FIGETBSZ:
601 return put_user(inode->i_sb->s_blocksize, argp); 624 return put_user(inode->i_sb->s_blocksize, argp);
602 625
626 case FICLONE:
627 return ioctl_file_clone(filp, arg, 0, 0, 0);
628
629 case FICLONERANGE:
630 return ioctl_file_clone_range(filp, argp);
631
603 default: 632 default:
604 if (S_ISREG(inode->i_mode)) 633 if (S_ISREG(inode->i_mode))
605 error = file_ioctl(filp, cmd, arg); 634 error = file_ioctl(filp, cmd, arg);