* FAILED: patch "[PATCH] Introduce cifs_copy_file_range()" failed to apply to 4.10-stable tree
@ 2017-04-10 14:21 gregkh
2017-04-10 14:23 ` Sachin Prabhu
0 siblings, 1 reply; 2+ messages in thread
From: gregkh @ 2017-04-10 14:21 UTC (permalink / raw)
To: sprabhu, pshilov, smfrench, stable; +Cc: stable
The patch below does not apply to the 4.10-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
>From 620d8745b35daaf507186c26b40c7ea02aed131e Mon Sep 17 00:00:00 2001
From: Sachin Prabhu <sprabhu@redhat.com>
Date: Fri, 10 Feb 2017 16:03:51 +0530
Subject: [PATCH] Introduce cifs_copy_file_range()
The earlier changes to copy range for cifs unintentionally disabled the more
common form of server side copy.
The patch introduces the file_operations helper cifs_copy_file_range()
which is used by the syscall copy_file_range. The new file operations
helper allows us to perform server side copies for SMB2.0 and 2.1
servers as well as SMB 3.0+ servers which do not support the ioctl
FSCTL_DUPLICATE_EXTENTS_TO_FILE.
The new helper uses the ioctl FSCTL_SRV_COPYCHUNK_WRITE to perform
server side copies. The helper is called by vfs_copy_file_range() only
once an attempt to clone the file using the ioctl
FSCTL_DUPLICATE_EXTENTS_TO_FILE has failed.
Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
CC: Stable <stable@vger.kernel.org>
Signed-off-by: Steve French <smfrench@gmail.com>
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
index 15e1db8738ae..dd3f5fabfdf6 100644
--- a/fs/cifs/cifsfs.c
+++ b/fs/cifs/cifsfs.c
@@ -972,6 +972,86 @@ static int cifs_clone_file_range(struct file *src_file, loff_t off,
return rc;
}
+ssize_t cifs_file_copychunk_range(unsigned int xid,
+ struct file *src_file, loff_t off,
+ struct file *dst_file, loff_t destoff,
+ size_t len, unsigned int flags)
+{
+ struct inode *src_inode = file_inode(src_file);
+ struct inode *target_inode = file_inode(dst_file);
+ struct cifsFileInfo *smb_file_src;
+ struct cifsFileInfo *smb_file_target;
+ struct cifs_tcon *src_tcon;
+ struct cifs_tcon *target_tcon;
+ ssize_t rc;
+
+ cifs_dbg(FYI, "copychunk range\n");
+
+ if (src_inode == target_inode) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ if (!src_file->private_data || !dst_file->private_data) {
+ rc = -EBADF;
+ cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n");
+ goto out;
+ }
+
+ rc = -EXDEV;
+ smb_file_target = dst_file->private_data;
+ smb_file_src = src_file->private_data;
+ src_tcon = tlink_tcon(smb_file_src->tlink);
+ target_tcon = tlink_tcon(smb_file_target->tlink);
+
+ if (src_tcon->ses != target_tcon->ses) {
+ cifs_dbg(VFS, "source and target of copy not on same server\n");
+ goto out;
+ }
+
+ /*
+ * Note: cifs case is easier than btrfs since server responsible for
+ * checks for proper open modes and file type and if it wants
+ * server could even support copy of range where source = target
+ */
+ lock_two_nondirectories(target_inode, src_inode);
+
+ cifs_dbg(FYI, "about to flush pages\n");
+ /* should we flush first and last page first */
+ truncate_inode_pages(&target_inode->i_data, 0);
+
+ if (target_tcon->ses->server->ops->copychunk_range)
+ rc = target_tcon->ses->server->ops->copychunk_range(xid,
+ smb_file_src, smb_file_target, off, len, destoff);
+ else
+ rc = -EOPNOTSUPP;
+
+ /* force revalidate of size and timestamps of target file now
+ * that target is updated on the server
+ */
+ CIFS_I(target_inode)->time = 0;
+ /* although unlocking in the reverse order from locking is not
+ * strictly necessary here it is a little cleaner to be consistent
+ */
+ unlock_two_nondirectories(src_inode, target_inode);
+
+out:
+ return rc;
+}
+
+static ssize_t cifs_copy_file_range(struct file *src_file, loff_t off,
+ struct file *dst_file, loff_t destoff,
+ size_t len, unsigned int flags)
+{
+ unsigned int xid = get_xid();
+ ssize_t rc;
+
+ rc = cifs_file_copychunk_range(xid, src_file, off, dst_file, destoff,
+ len, flags);
+ free_xid(xid);
+ return rc;
+}
+
const struct file_operations cifs_file_ops = {
.read_iter = cifs_loose_read_iter,
.write_iter = cifs_file_write_iter,
@@ -984,6 +1064,7 @@ const struct file_operations cifs_file_ops = {
.splice_read = generic_file_splice_read,
.llseek = cifs_llseek,
.unlocked_ioctl = cifs_ioctl,
+ .copy_file_range = cifs_copy_file_range,
.clone_file_range = cifs_clone_file_range,
.setlease = cifs_setlease,
.fallocate = cifs_fallocate,
@@ -1001,6 +1082,7 @@ const struct file_operations cifs_file_strict_ops = {
.splice_read = generic_file_splice_read,
.llseek = cifs_llseek,
.unlocked_ioctl = cifs_ioctl,
+ .copy_file_range = cifs_copy_file_range,
.clone_file_range = cifs_clone_file_range,
.setlease = cifs_setlease,
.fallocate = cifs_fallocate,
@@ -1018,6 +1100,7 @@ const struct file_operations cifs_file_direct_ops = {
.mmap = cifs_file_mmap,
.splice_read = generic_file_splice_read,
.unlocked_ioctl = cifs_ioctl,
+ .copy_file_range = cifs_copy_file_range,
.clone_file_range = cifs_clone_file_range,
.llseek = cifs_llseek,
.setlease = cifs_setlease,
@@ -1035,6 +1118,7 @@ const struct file_operations cifs_file_nobrl_ops = {
.splice_read = generic_file_splice_read,
.llseek = cifs_llseek,
.unlocked_ioctl = cifs_ioctl,
+ .copy_file_range = cifs_copy_file_range,
.clone_file_range = cifs_clone_file_range,
.setlease = cifs_setlease,
.fallocate = cifs_fallocate,
@@ -1051,6 +1135,7 @@ const struct file_operations cifs_file_strict_nobrl_ops = {
.splice_read = generic_file_splice_read,
.llseek = cifs_llseek,
.unlocked_ioctl = cifs_ioctl,
+ .copy_file_range = cifs_copy_file_range,
.clone_file_range = cifs_clone_file_range,
.setlease = cifs_setlease,
.fallocate = cifs_fallocate,
@@ -1067,6 +1152,7 @@ const struct file_operations cifs_file_direct_nobrl_ops = {
.mmap = cifs_file_mmap,
.splice_read = generic_file_splice_read,
.unlocked_ioctl = cifs_ioctl,
+ .copy_file_range = cifs_copy_file_range,
.clone_file_range = cifs_clone_file_range,
.llseek = cifs_llseek,
.setlease = cifs_setlease,
@@ -1078,6 +1164,7 @@ const struct file_operations cifs_dir_ops = {
.release = cifs_closedir,
.read = generic_read_dir,
.unlocked_ioctl = cifs_ioctl,
+ .copy_file_range = cifs_copy_file_range,
.clone_file_range = cifs_clone_file_range,
.llseek = generic_file_llseek,
};
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index da717fee3026..30bf89b1fd9a 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -139,6 +139,11 @@ extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
# define cifs_listxattr NULL
#endif
+extern ssize_t cifs_file_copychunk_range(unsigned int xid,
+ struct file *src_file, loff_t off,
+ struct file *dst_file, loff_t destoff,
+ size_t len, unsigned int flags);
+
extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
#ifdef CONFIG_CIFS_NFSD_EXPORT
extern const struct export_operations cifs_export_ops;
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 57c594827cb3..d07f13a63369 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -408,10 +408,10 @@ struct smb_version_operations {
char * (*create_lease_buf)(u8 *, u8);
/* parse lease context buffer and return oplock/epoch info */
__u8 (*parse_lease_buf)(void *, unsigned int *);
- int (*copychunk_range)(const unsigned int,
+ ssize_t (*copychunk_range)(const unsigned int,
struct cifsFileInfo *src_file,
- struct cifsFileInfo *target_file, u64 src_off, u64 len,
- u64 dest_off);
+ struct cifsFileInfo *target_file,
+ u64 src_off, u64 len, u64 dest_off);
int (*duplicate_extents)(const unsigned int, struct cifsFileInfo *src,
struct cifsFileInfo *target_file, u64 src_off, u64 len,
u64 dest_off);
diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
index 9bf0f94fae63..265c45fe4ea5 100644
--- a/fs/cifs/ioctl.c
+++ b/fs/cifs/ioctl.c
@@ -34,63 +34,6 @@
#include "cifs_ioctl.h"
#include <linux/btrfs.h>
-static int cifs_file_copychunk_range(unsigned int xid, struct file *src_file,
- struct file *dst_file)
-{
- struct inode *src_inode = file_inode(src_file);
- struct inode *target_inode = file_inode(dst_file);
- struct cifsFileInfo *smb_file_src;
- struct cifsFileInfo *smb_file_target;
- struct cifs_tcon *src_tcon;
- struct cifs_tcon *target_tcon;
- int rc;
-
- cifs_dbg(FYI, "ioctl copychunk range\n");
-
- if (!src_file->private_data || !dst_file->private_data) {
- rc = -EBADF;
- cifs_dbg(VFS, "missing cifsFileInfo on copy range src file\n");
- goto out;
- }
-
- rc = -EXDEV;
- smb_file_target = dst_file->private_data;
- smb_file_src = src_file->private_data;
- src_tcon = tlink_tcon(smb_file_src->tlink);
- target_tcon = tlink_tcon(smb_file_target->tlink);
-
- if (src_tcon->ses != target_tcon->ses) {
- cifs_dbg(VFS, "source and target of copy not on same server\n");
- goto out;
- }
-
- /*
- * Note: cifs case is easier than btrfs since server responsible for
- * checks for proper open modes and file type and if it wants
- * server could even support copy of range where source = target
- */
- lock_two_nondirectories(target_inode, src_inode);
-
- cifs_dbg(FYI, "about to flush pages\n");
- /* should we flush first and last page first */
- truncate_inode_pages(&target_inode->i_data, 0);
-
- if (target_tcon->ses->server->ops->copychunk_range)
- rc = target_tcon->ses->server->ops->copychunk_range(xid,
- smb_file_src, smb_file_target, 0, src_inode->i_size, 0);
- else
- rc = -EOPNOTSUPP;
-
- /* force revalidate of size and timestamps of target file now
- that target is updated on the server */
- CIFS_I(target_inode)->time = 0;
- /* although unlocking in the reverse order from locking is not
- strictly necessary here it is a little cleaner to be consistent */
- unlock_two_nondirectories(src_inode, target_inode);
-out:
- return rc;
-}
-
static long cifs_ioctl_copychunk(unsigned int xid, struct file *dst_file,
unsigned long srcfd)
{
@@ -129,7 +72,8 @@ 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, dst_file);
+ rc = cifs_file_copychunk_range(xid, src_file.file, 0, dst_file, 0,
+ src_inode->i_size, 0);
out_fput:
fdput(src_file);
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index 3f12e0992b9b..063e59d543f9 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -592,7 +592,7 @@ SMB2_request_res_key(const unsigned int xid, struct cifs_tcon *tcon,
return rc;
}
-static int
+static ssize_t
smb2_copychunk_range(const unsigned int xid,
struct cifsFileInfo *srcfile,
struct cifsFileInfo *trgtfile, u64 src_off,
@@ -605,6 +605,7 @@ smb2_copychunk_range(const unsigned int xid,
struct cifs_tcon *tcon;
int chunks_copied = 0;
bool chunk_sizes_updated = false;
+ ssize_t bytes_written, total_bytes_written = 0;
pcchunk = kmalloc(sizeof(struct copychunk_ioctl), GFP_KERNEL);
@@ -669,14 +670,16 @@ smb2_copychunk_range(const unsigned int xid,
}
chunks_copied++;
- src_off += le32_to_cpu(retbuf->TotalBytesWritten);
- dest_off += le32_to_cpu(retbuf->TotalBytesWritten);
- len -= le32_to_cpu(retbuf->TotalBytesWritten);
+ bytes_written = le32_to_cpu(retbuf->TotalBytesWritten);
+ src_off += bytes_written;
+ dest_off += bytes_written;
+ len -= bytes_written;
+ total_bytes_written += bytes_written;
- cifs_dbg(FYI, "Chunks %d PartialChunk %d Total %d\n",
+ cifs_dbg(FYI, "Chunks %d PartialChunk %d Total %zu\n",
le32_to_cpu(retbuf->ChunksWritten),
le32_to_cpu(retbuf->ChunkBytesWritten),
- le32_to_cpu(retbuf->TotalBytesWritten));
+ bytes_written);
} else if (rc == -EINVAL) {
if (ret_data_len != sizeof(struct copychunk_ioctl_rsp))
goto cchunk_out;
@@ -713,7 +716,10 @@ smb2_copychunk_range(const unsigned int xid,
cchunk_out:
kfree(pcchunk);
kfree(retbuf);
- return rc;
+ if (rc)
+ return rc;
+ else
+ return total_bytes_written;
}
static int
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: FAILED: patch "[PATCH] Introduce cifs_copy_file_range()" failed to apply to 4.10-stable tree
2017-04-10 14:21 FAILED: patch "[PATCH] Introduce cifs_copy_file_range()" failed to apply to 4.10-stable tree gregkh
@ 2017-04-10 14:23 ` Sachin Prabhu
0 siblings, 0 replies; 2+ messages in thread
From: Sachin Prabhu @ 2017-04-10 14:23 UTC (permalink / raw)
To: gregkh, pshilov, smfrench, stable
On Mon, 2017-04-10 at 16:21 +0200, gregkh@linuxfoundation.org wrote:
> The patch below does not apply to the 4.10-stable tree.
> If someone wants it applied there, or to any other stable or longterm
> tree, then please email the backport, including the original git
> commit
> id to <stable@vger.kernel.org>.
>
> thanks,
>
> greg k-h
Hello Greg,
We found a regression in this patch too so would prefer to not have
this backported for now.
Sachin Prabhu
>
> ------------------ original commit in Linus's tree ------------------
>
> From 620d8745b35daaf507186c26b40c7ea02aed131e Mon Sep 17 00:00:00
> 2001
> From: Sachin Prabhu <sprabhu@redhat.com>
> Date: Fri, 10 Feb 2017 16:03:51 +0530
> Subject: [PATCH] Introduce cifs_copy_file_range()
>
> The earlier changes to copy range for cifs unintentionally disabled
> the more
> common form of server side copy.
>
> The patch introduces the file_operations helper
> cifs_copy_file_range()
> which is used by the syscall copy_file_range. The new file operations
> helper allows us to perform server side copies for SMB2.0 and 2.1
> servers as well as SMB 3.0+ servers which do not support the ioctl
> FSCTL_DUPLICATE_EXTENTS_TO_FILE.
>
> The new helper uses the ioctl FSCTL_SRV_COPYCHUNK_WRITE to perform
> server side copies. The helper is called by vfs_copy_file_range()
> only
> once an attempt to clone the file using the ioctl
> FSCTL_DUPLICATE_EXTENTS_TO_FILE has failed.
>
> Signed-off-by: Sachin Prabhu <sprabhu@redhat.com>
> Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
> CC: Stable <stable@vger.kernel.org>
> Signed-off-by: Steve French <smfrench@gmail.com>
>
> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
> index 15e1db8738ae..dd3f5fabfdf6 100644
> --- a/fs/cifs/cifsfs.c
> +++ b/fs/cifs/cifsfs.c
> @@ -972,6 +972,86 @@ static int cifs_clone_file_range(struct file
> *src_file, loff_t off,
> return rc;
> }
>
> +ssize_t cifs_file_copychunk_range(unsigned int xid,
> + struct file *src_file, loff_t off,
> + struct file *dst_file, loff_t
> destoff,
> + size_t len, unsigned int flags)
> +{
> + struct inode *src_inode = file_inode(src_file);
> + struct inode *target_inode = file_inode(dst_file);
> + struct cifsFileInfo *smb_file_src;
> + struct cifsFileInfo *smb_file_target;
> + struct cifs_tcon *src_tcon;
> + struct cifs_tcon *target_tcon;
> + ssize_t rc;
> +
> + cifs_dbg(FYI, "copychunk range\n");
> +
> + if (src_inode == target_inode) {
> + rc = -EINVAL;
> + goto out;
> + }
> +
> + if (!src_file->private_data || !dst_file->private_data) {
> + rc = -EBADF;
> + cifs_dbg(VFS, "missing cifsFileInfo on copy range
> src file\n");
> + goto out;
> + }
> +
> + rc = -EXDEV;
> + smb_file_target = dst_file->private_data;
> + smb_file_src = src_file->private_data;
> + src_tcon = tlink_tcon(smb_file_src->tlink);
> + target_tcon = tlink_tcon(smb_file_target->tlink);
> +
> + if (src_tcon->ses != target_tcon->ses) {
> + cifs_dbg(VFS, "source and target of copy not on same
> server\n");
> + goto out;
> + }
> +
> + /*
> + * Note: cifs case is easier than btrfs since server
> responsible for
> + * checks for proper open modes and file type and if it
> wants
> + * server could even support copy of range where source =
> target
> + */
> + lock_two_nondirectories(target_inode, src_inode);
> +
> + cifs_dbg(FYI, "about to flush pages\n");
> + /* should we flush first and last page first */
> + truncate_inode_pages(&target_inode->i_data, 0);
> +
> + if (target_tcon->ses->server->ops->copychunk_range)
> + rc = target_tcon->ses->server->ops-
> >copychunk_range(xid,
> + smb_file_src, smb_file_target, off, len,
> destoff);
> + else
> + rc = -EOPNOTSUPP;
> +
> + /* force revalidate of size and timestamps of target file
> now
> + * that target is updated on the server
> + */
> + CIFS_I(target_inode)->time = 0;
> + /* although unlocking in the reverse order from locking is
> not
> + * strictly necessary here it is a little cleaner to be
> consistent
> + */
> + unlock_two_nondirectories(src_inode, target_inode);
> +
> +out:
> + return rc;
> +}
> +
> +static ssize_t cifs_copy_file_range(struct file *src_file, loff_t
> off,
> + struct file *dst_file, loff_t
> destoff,
> + size_t len, unsigned int flags)
> +{
> + unsigned int xid = get_xid();
> + ssize_t rc;
> +
> + rc = cifs_file_copychunk_range(xid, src_file, off, dst_file,
> destoff,
> + len, flags);
> + free_xid(xid);
> + return rc;
> +}
> +
> const struct file_operations cifs_file_ops = {
> .read_iter = cifs_loose_read_iter,
> .write_iter = cifs_file_write_iter,
> @@ -984,6 +1064,7 @@ const struct file_operations cifs_file_ops = {
> .splice_read = generic_file_splice_read,
> .llseek = cifs_llseek,
> .unlocked_ioctl = cifs_ioctl,
> + .copy_file_range = cifs_copy_file_range,
> .clone_file_range = cifs_clone_file_range,
> .setlease = cifs_setlease,
> .fallocate = cifs_fallocate,
> @@ -1001,6 +1082,7 @@ const struct file_operations
> cifs_file_strict_ops = {
> .splice_read = generic_file_splice_read,
> .llseek = cifs_llseek,
> .unlocked_ioctl = cifs_ioctl,
> + .copy_file_range = cifs_copy_file_range,
> .clone_file_range = cifs_clone_file_range,
> .setlease = cifs_setlease,
> .fallocate = cifs_fallocate,
> @@ -1018,6 +1100,7 @@ const struct file_operations
> cifs_file_direct_ops = {
> .mmap = cifs_file_mmap,
> .splice_read = generic_file_splice_read,
> .unlocked_ioctl = cifs_ioctl,
> + .copy_file_range = cifs_copy_file_range,
> .clone_file_range = cifs_clone_file_range,
> .llseek = cifs_llseek,
> .setlease = cifs_setlease,
> @@ -1035,6 +1118,7 @@ const struct file_operations
> cifs_file_nobrl_ops = {
> .splice_read = generic_file_splice_read,
> .llseek = cifs_llseek,
> .unlocked_ioctl = cifs_ioctl,
> + .copy_file_range = cifs_copy_file_range,
> .clone_file_range = cifs_clone_file_range,
> .setlease = cifs_setlease,
> .fallocate = cifs_fallocate,
> @@ -1051,6 +1135,7 @@ const struct file_operations
> cifs_file_strict_nobrl_ops = {
> .splice_read = generic_file_splice_read,
> .llseek = cifs_llseek,
> .unlocked_ioctl = cifs_ioctl,
> + .copy_file_range = cifs_copy_file_range,
> .clone_file_range = cifs_clone_file_range,
> .setlease = cifs_setlease,
> .fallocate = cifs_fallocate,
> @@ -1067,6 +1152,7 @@ const struct file_operations
> cifs_file_direct_nobrl_ops = {
> .mmap = cifs_file_mmap,
> .splice_read = generic_file_splice_read,
> .unlocked_ioctl = cifs_ioctl,
> + .copy_file_range = cifs_copy_file_range,
> .clone_file_range = cifs_clone_file_range,
> .llseek = cifs_llseek,
> .setlease = cifs_setlease,
> @@ -1078,6 +1164,7 @@ const struct file_operations cifs_dir_ops = {
> .release = cifs_closedir,
> .read = generic_read_dir,
> .unlocked_ioctl = cifs_ioctl,
> + .copy_file_range = cifs_copy_file_range,
> .clone_file_range = cifs_clone_file_range,
> .llseek = generic_file_llseek,
> };
> diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
> index da717fee3026..30bf89b1fd9a 100644
> --- a/fs/cifs/cifsfs.h
> +++ b/fs/cifs/cifsfs.h
> @@ -139,6 +139,11 @@ extern ssize_t cifs_listxattr(struct
> dentry *, char *, size_t);
> # define cifs_listxattr NULL
> #endif
>
> +extern ssize_t cifs_file_copychunk_range(unsigned int xid,
> + struct file *src_file,
> loff_t off,
> + struct file *dst_file,
> loff_t destoff,
> + size_t len, unsigned int
> flags);
> +
> extern long cifs_ioctl(struct file *filep, unsigned int cmd,
> unsigned long arg);
> #ifdef CONFIG_CIFS_NFSD_EXPORT
> extern const struct export_operations cifs_export_ops;
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 57c594827cb3..d07f13a63369 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -408,10 +408,10 @@ struct smb_version_operations {
> char * (*create_lease_buf)(u8 *, u8);
> /* parse lease context buffer and return oplock/epoch info
> */
> __u8 (*parse_lease_buf)(void *, unsigned int *);
> - int (*copychunk_range)(const unsigned int,
> + ssize_t (*copychunk_range)(const unsigned int,
> struct cifsFileInfo *src_file,
> - struct cifsFileInfo *target_file, u64
> src_off, u64 len,
> - u64 dest_off);
> + struct cifsFileInfo *target_file,
> + u64 src_off, u64 len, u64 dest_off);
> int (*duplicate_extents)(const unsigned int, struct
> cifsFileInfo *src,
> struct cifsFileInfo *target_file, u64
> src_off, u64 len,
> u64 dest_off);
> diff --git a/fs/cifs/ioctl.c b/fs/cifs/ioctl.c
> index 9bf0f94fae63..265c45fe4ea5 100644
> --- a/fs/cifs/ioctl.c
> +++ b/fs/cifs/ioctl.c
> @@ -34,63 +34,6 @@
> #include "cifs_ioctl.h"
> #include <linux/btrfs.h>
>
> -static int cifs_file_copychunk_range(unsigned int xid, struct file
> *src_file,
> - struct file *dst_file)
> -{
> - struct inode *src_inode = file_inode(src_file);
> - struct inode *target_inode = file_inode(dst_file);
> - struct cifsFileInfo *smb_file_src;
> - struct cifsFileInfo *smb_file_target;
> - struct cifs_tcon *src_tcon;
> - struct cifs_tcon *target_tcon;
> - int rc;
> -
> - cifs_dbg(FYI, "ioctl copychunk range\n");
> -
> - if (!src_file->private_data || !dst_file->private_data) {
> - rc = -EBADF;
> - cifs_dbg(VFS, "missing cifsFileInfo on copy range
> src file\n");
> - goto out;
> - }
> -
> - rc = -EXDEV;
> - smb_file_target = dst_file->private_data;
> - smb_file_src = src_file->private_data;
> - src_tcon = tlink_tcon(smb_file_src->tlink);
> - target_tcon = tlink_tcon(smb_file_target->tlink);
> -
> - if (src_tcon->ses != target_tcon->ses) {
> - cifs_dbg(VFS, "source and target of copy not on same
> server\n");
> - goto out;
> - }
> -
> - /*
> - * Note: cifs case is easier than btrfs since server
> responsible for
> - * checks for proper open modes and file type and if it
> wants
> - * server could even support copy of range where source =
> target
> - */
> - lock_two_nondirectories(target_inode, src_inode);
> -
> - cifs_dbg(FYI, "about to flush pages\n");
> - /* should we flush first and last page first */
> - truncate_inode_pages(&target_inode->i_data, 0);
> -
> - if (target_tcon->ses->server->ops->copychunk_range)
> - rc = target_tcon->ses->server->ops-
> >copychunk_range(xid,
> - smb_file_src, smb_file_target, 0, src_inode-
> >i_size, 0);
> - else
> - rc = -EOPNOTSUPP;
> -
> - /* force revalidate of size and timestamps of target file
> now
> - that target is updated on the server */
> - CIFS_I(target_inode)->time = 0;
> - /* although unlocking in the reverse order from locking is
> not
> - strictly necessary here it is a little cleaner to be
> consistent */
> - unlock_two_nondirectories(src_inode, target_inode);
> -out:
> - return rc;
> -}
> -
> static long cifs_ioctl_copychunk(unsigned int xid, struct file
> *dst_file,
> unsigned long srcfd)
> {
> @@ -129,7 +72,8 @@ 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,
> dst_file);
> + rc = cifs_file_copychunk_range(xid, src_file.file, 0,
> dst_file, 0,
> + src_inode->i_size, 0);
>
> out_fput:
> fdput(src_file);
> diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
> index 3f12e0992b9b..063e59d543f9 100644
> --- a/fs/cifs/smb2ops.c
> +++ b/fs/cifs/smb2ops.c
> @@ -592,7 +592,7 @@ SMB2_request_res_key(const unsigned int xid,
> struct cifs_tcon *tcon,
> return rc;
> }
>
> -static int
> +static ssize_t
> smb2_copychunk_range(const unsigned int xid,
> struct cifsFileInfo *srcfile,
> struct cifsFileInfo *trgtfile, u64 src_off,
> @@ -605,6 +605,7 @@ smb2_copychunk_range(const unsigned int xid,
> struct cifs_tcon *tcon;
> int chunks_copied = 0;
> bool chunk_sizes_updated = false;
> + ssize_t bytes_written, total_bytes_written = 0;
>
> pcchunk = kmalloc(sizeof(struct copychunk_ioctl),
> GFP_KERNEL);
>
> @@ -669,14 +670,16 @@ smb2_copychunk_range(const unsigned int xid,
> }
> chunks_copied++;
>
> - src_off += le32_to_cpu(retbuf-
> >TotalBytesWritten);
> - dest_off += le32_to_cpu(retbuf-
> >TotalBytesWritten);
> - len -= le32_to_cpu(retbuf-
> >TotalBytesWritten);
> + bytes_written = le32_to_cpu(retbuf-
> >TotalBytesWritten);
> + src_off += bytes_written;
> + dest_off += bytes_written;
> + len -= bytes_written;
> + total_bytes_written += bytes_written;
>
> - cifs_dbg(FYI, "Chunks %d PartialChunk %d
> Total %d\n",
> + cifs_dbg(FYI, "Chunks %d PartialChunk %d
> Total %zu\n",
> le32_to_cpu(retbuf->ChunksWritten),
> le32_to_cpu(retbuf-
> >ChunkBytesWritten),
> - le32_to_cpu(retbuf-
> >TotalBytesWritten));
> + bytes_written);
> } else if (rc == -EINVAL) {
> if (ret_data_len != sizeof(struct
> copychunk_ioctl_rsp))
> goto cchunk_out;
> @@ -713,7 +716,10 @@ smb2_copychunk_range(const unsigned int xid,
> cchunk_out:
> kfree(pcchunk);
> kfree(retbuf);
> - return rc;
> + if (rc)
> + return rc;
> + else
> + return total_bytes_written;
> }
>
> static int
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2017-04-10 14:23 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-04-10 14:21 FAILED: patch "[PATCH] Introduce cifs_copy_file_range()" failed to apply to 4.10-stable tree gregkh
2017-04-10 14:23 ` Sachin Prabhu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).