[PATCH] cifs: add ioctl for SRV_COPYCHUNK range

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Add a new ioctl for COPYCHUNK that copies a region. The existing
COPYCHUNK can only be used to copy a whole file.

Signed-off-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx>
---
 fs/cifs/cifs_ioctl.h |  8 ++++++++
 fs/cifs/ioctl.c      | 53 ++++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 55 insertions(+), 6 deletions(-)

diff --git a/fs/cifs/cifs_ioctl.h b/fs/cifs/cifs_ioctl.h
index 57ff0756e30c..b40b9b608dde 100644
--- a/fs/cifs/cifs_ioctl.h
+++ b/fs/cifs/cifs_ioctl.h
@@ -43,8 +43,16 @@ struct smb_snapshot_array {
 	/*	snapshots[]; */
 } __packed;
 
+struct smb_srv_copychunk {
+	__u32   src_fd;
+	__u32   length;
+	__u64   src_offset;
+	__u64   dst_offset;
+} __packed;
+
 #define CIFS_IOCTL_MAGIC	0xCF
 #define CIFS_IOC_COPYCHUNK_FILE	_IOW(CIFS_IOCTL_MAGIC, 3, int)
 #define CIFS_IOC_SET_INTEGRITY  _IO(CIFS_IOCTL_MAGIC, 4)
 #define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
 #define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
+#define CIFS_IOC_COPYCHUNK _IOW(CIFS_IOCTL_MAGIC, 7, struct smb_srv_copychunk)
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 54f32f9143a9..91f87ea01be0 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -34,14 +34,13 @@
 #include "cifs_ioctl.h"
 #include <linux/btrfs.h>
 
-static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
-			unsigned long srcfd)
+static long _cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
+				  struct smb_srv_copychunk *cc)
 {
 	int rc;
 	struct fd src_file;
 	struct inode *src_inode;
 
-	cifs_dbg(FYI, "ioctl copychunk range\n");
 	/* the destination must be opened for writing */
 	if (!(dst_file->f_mode & FMODE_WRITE)) {
 		cifs_dbg(FYI, "file target not open for write\n");
@@ -55,7 +54,7 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
 		return rc;
 	}
 
-	src_file = fdget(srcfd);
+	src_file = fdget(cc->src_fd);
 	if (!src_file.file) {
 		rc = -EBADF;
 		goto out_drop_write;
@@ -72,8 +71,9 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
 	if (S_ISDIR(src_inode->i_mode))
 		goto out_fput;
 
-	rc = cifs_file_copychunk_range(xid, src_file.file, 0, dst_file, 0,
-					src_inode->i_size, 0);
+	rc = cifs_file_copychunk_range(xid, src_file.file, cc->src_offset,
+				       dst_file, cc->dst_offset,
+				       cc->length, 0);
 	if (rc > 0)
 		rc = 0;
 out_fput:
@@ -83,6 +83,44 @@ static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
 	return rc;
 }
 
+static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
+				 unsigned long p)
+{
+	void __user *arg = (void __user *)p;
+	struct smb_srv_copychunk cc;
+
+	cifs_dbg(FYI, "ioctl copychunk range\n");
+
+	if (copy_from_user(&cc, arg, sizeof(cc)))
+		return -EFAULT;
+
+	return _cifs_ioctl_copychunk(xid, dst_file, &cc);
+}
+
+static long cifs_ioctl_copychunk_file(unsigned int xid, struct file *dst_file,
+				      unsigned long srcfd)
+{
+	struct smb_srv_copychunk cc;
+	struct fd src_file;
+	struct inode *src_inode;
+
+	cifs_dbg(FYI, "ioctl copychunk file\n");
+
+	src_file = fdget(srcfd);
+	if (!src_file.file) {
+		mnt_drop_write_file(dst_file);
+		return -EBADF;
+	}
+	src_inode = file_inode(src_file.file);
+
+	memset(&cc, 0, sizeof(struct smb_srv_copychunk));
+	cc.src_fd = srcfd;
+	cc.length = src_inode->i_size;
+	fdput(src_file);
+
+	return _cifs_ioctl_copychunk(xid, dst_file, &cc);
+}
+
 static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon,
 				void __user *arg)
 {
@@ -194,6 +232,9 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
 			}
 			break;
 		case CIFS_IOC_COPYCHUNK_FILE:
+			rc = cifs_ioctl_copychunk_file(xid, filep, arg);
+			break;
+		case CIFS_IOC_COPYCHUNK:
 			rc = cifs_ioctl_copychunk(xid, filep, arg);
 			break;
 		case CIFS_IOC_SET_INTEGRITY:
-- 
2.13.3




[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux