summaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4file.c
diff options
context:
space:
mode:
authorOlga Kornievskaia <kolga@netapp.com>2019-06-04 22:14:30 +0200
committerOlga Kornievskaia <olga.kornievskaia@gmail.com>2019-10-09 18:05:45 +0200
commit0491567b51efeca807da1125a1a0d5193875e286 (patch)
treef1c88abfe8baacdf33d4dbed412812eb8b2f6f76 /fs/nfs/nfs4file.c
parentNFS NFSD: defining nl4_servers structure needed by both (diff)
downloadlinux-0491567b51efeca807da1125a1a0d5193875e286.tar.xz
linux-0491567b51efeca807da1125a1a0d5193875e286.zip
NFS: add COPY_NOTIFY operation
Try using the delegation stateid, then the open stateid. Only NL4_NETATTR, No support for NL4_NAME and NL4_URL. Allow only one source server address to be returned for now. To distinguish between same server copy offload ("intra") and a copy between different server ("inter"), do a check of server owner identity and also make sure server is capable of doing a copy offload. Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4file.c')
-rw-r--r--fs/nfs/nfs4file.c20
1 files changed, 19 insertions, 1 deletions
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index 339663d04bf8..686a6c4071e3 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -133,6 +133,9 @@ static ssize_t __nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
struct file *file_out, loff_t pos_out,
size_t count, unsigned int flags)
{
+ struct nfs42_copy_notify_res *cn_resp = NULL;
+ ssize_t ret;
+
/* Only offload copy if superblock is the same */
if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb)
return -EXDEV;
@@ -140,7 +143,22 @@ 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;
- return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
+ if (!nfs42_files_from_same_server(file_in, file_out)) {
+ cn_resp = kzalloc(sizeof(struct nfs42_copy_notify_res),
+ GFP_NOFS);
+ if (unlikely(cn_resp == NULL))
+ return -ENOMEM;
+
+ ret = nfs42_proc_copy_notify(file_in, file_out, cn_resp);
+ if (ret) {
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+ }
+ ret = nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
+out:
+ kfree(cn_resp);
+ return ret;
}
static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,