Commit 12751010 authored by Olga Kornievskaia's avatar Olga Kornievskaia Committed by Olga Kornievskaia
Browse files

NFS based on file size issue sync copy or fallback to generic copy offload



For small file sizes, it make sense to issue a synchronous copy (and
save an RPC callback operation). Also, for the inter copy offload,
copy len must be larger than the cost of doing a mount between the
destination and source server (14RPCs are sent during 4.x mount).

Signed-off-by: default avatarOlga Kornievskaia <kolga@netapp.com>
parent 0e65a32c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@
#ifdef CONFIG_NFS_V4_2
int nfs42_proc_allocate(struct file *, loff_t, loff_t);
ssize_t nfs42_proc_copy(struct file *, loff_t, struct file *, loff_t, size_t,
			struct nl4_server *, nfs4_stateid *);
			struct nl4_server *, nfs4_stateid *, bool);
int nfs42_proc_deallocate(struct file *, loff_t, loff_t);
loff_t nfs42_proc_llseek(struct file *, loff_t, int);
int nfs42_proc_layoutstats_generic(struct nfs_server *,
+2 −2
Original line number Diff line number Diff line
@@ -357,7 +357,7 @@ static ssize_t _nfs42_proc_copy(struct file *src,
ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
			struct file *dst, loff_t pos_dst, size_t count,
			struct nl4_server *nss,
			nfs4_stateid *cnr_stateid)
			nfs4_stateid *cnr_stateid, bool sync)
{
	struct nfs_server *server = NFS_SERVER(file_inode(dst));
	struct nfs_lock_context *src_lock;
@@ -368,7 +368,7 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
		.dst_fh		= NFS_FH(file_inode(dst)),
		.dst_pos	= pos_dst,
		.count		= count,
		.sync		= false,
		.sync		= sync,
	};
	struct nfs42_copy_res res;
	struct nfs4_exception src_exception = {
+15 −1
Original line number Diff line number Diff line
@@ -138,6 +138,7 @@ static ssize_t __nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
	struct nl4_server *nss = NULL;
	nfs4_stateid *cnrs = NULL;
	ssize_t ret;
	bool sync = false;

	/* Only offload copy if superblock is the same */
	if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb)
@@ -146,8 +147,21 @@ static ssize_t __nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
		return -EOPNOTSUPP;
	if (file_inode(file_in) == file_inode(file_out))
		return -EOPNOTSUPP;
	/* if the copy size if smaller than 2 RPC payloads, make it
	 * synchronous
	 */
	if (count <= 2 * NFS_SERVER(file_inode(file_in))->rsize)
		sync = true;
retry:
	if (!nfs42_files_from_same_server(file_in, file_out)) {
		/* for inter copy, if copy size if smaller than 12 RPC
		 * payloads, fallback to traditional copy. There are
		 * 14 RPCs during an NFSv4.x mount between source/dest
		 * servers.
		 */
		if (sync ||
			count <= 14 * NFS_SERVER(file_inode(file_in))->rsize)
			return -EOPNOTSUPP;
		cn_resp = kzalloc(sizeof(struct nfs42_copy_notify_res),
				GFP_NOFS);
		if (unlikely(cn_resp == NULL))
@@ -162,7 +176,7 @@ static ssize_t __nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
		cnrs = &cn_resp->cnr_stateid;
	}
	ret = nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count,
				nss, cnrs);
				nss, cnrs, sync);
out:
	kfree(cn_resp);
	if (ret == -EAGAIN)