All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sachin Prabhu <sprabhu@redhat.com>
To: gregkh@linuxfoundation.org, pshilov@microsoft.com,
	smfrench@gmail.com, stable@vger.kernel.org
Subject: Re: FAILED: patch "[PATCH] Introduce cifs_copy_file_range()" failed to apply to 4.10-stable tree
Date: Mon, 10 Apr 2017 15:23:56 +0100	[thread overview]
Message-ID: <1491834236.8507.1.camel@redhat.com> (raw)
In-Reply-To: <149183407518197@kroah.com>

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
> 

      reply	other threads:[~2017-04-10 14:23 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1491834236.8507.1.camel@redhat.com \
    --to=sprabhu@redhat.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=pshilov@microsoft.com \
    --cc=smfrench@gmail.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.