diff mbox series

[v1,04/13] NFS inter ssc open

Message ID 20181019152905.32418-5-olga.kornievskaia@gmail.com (mailing list archive)
State New, archived
Headers show
Series server-side support for "inter" SSC copy | expand

Commit Message

Olga Kornievskaia Oct. 19, 2018, 3:28 p.m. UTC
From: Olga Kornievskaia <kolga@netapp.com>

NFSv4.2 inter server to server copy requires the destination server to
READ the data from the source server using the provided stateid and
file handle.

Given an NFSv4 stateid and filehandle from the COPY operaion, provide the
destination server with an NFS client function to create a struct file
suitable for the destiniation server to READ the data to be copied.

Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
---
 fs/nfs/nfs4_fs.h  |  7 ++++
 fs/nfs/nfs4file.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/nfs/nfs4proc.c |  5 ++-
 3 files changed, 107 insertions(+), 3 deletions(-)

Comments

J. Bruce Fields Oct. 31, 2018, 6:40 p.m. UTC | #1
Just to pick one thing that I don't understand yet:

On Fri, Oct 19, 2018 at 11:28:56AM -0400, Olga Kornievskaia wrote:
> +EXPORT_SYMBOL_GPL(nfs42_ssc_open);
> +void nfs42_ssc_close(struct file *filep)
> +{
> +	struct nfs_open_context *ctx = nfs_file_open_context(filep);
> +
> +	ctx->state->flags = 0;

Why is this needed?

Also, given the name and the pairing with nfs42_ssc_open(), would it be
more logical for it to do the fput() as well?

--b.
Olga Kornievskaia Oct. 31, 2018, 6:54 p.m. UTC | #2
On Wed, Oct 31, 2018 at 2:40 PM J. Bruce Fields <bfields@fieldses.org> wrote:
>
> Just to pick one thing that I don't understand yet:
>
> On Fri, Oct 19, 2018 at 11:28:56AM -0400, Olga Kornievskaia wrote:
> > +EXPORT_SYMBOL_GPL(nfs42_ssc_open);
> > +void nfs42_ssc_close(struct file *filep)
> > +{
> > +     struct nfs_open_context *ctx = nfs_file_open_context(filep);
> > +
> > +     ctx->state->flags = 0;
>
> Why is this needed?

This is needed so that CLOSE isn't going on the wire but closed internally.

> Also, given the name and the pairing with nfs42_ssc_open(), would it be
> more logical for it to do the fput() as well?

I'd like to keep that fput() in the nfsd to make it consistent with
the "intra". There are fput()s for intra but intra doesn't call into
nfs42_ssc_close().
J. Bruce Fields Nov. 1, 2018, 8:12 p.m. UTC | #3
On Wed, Oct 31, 2018 at 02:54:51PM -0400, Olga Kornievskaia wrote:
> On Wed, Oct 31, 2018 at 2:40 PM J. Bruce Fields <bfields@fieldses.org> wrote:
> >
> > Just to pick one thing that I don't understand yet:
> >
> > On Fri, Oct 19, 2018 at 11:28:56AM -0400, Olga Kornievskaia wrote:
> > > +EXPORT_SYMBOL_GPL(nfs42_ssc_open);
> > > +void nfs42_ssc_close(struct file *filep)
> > > +{
> > > +     struct nfs_open_context *ctx = nfs_file_open_context(filep);
> > > +
> > > +     ctx->state->flags = 0;
> >
> > Why is this needed?
> 
> This is needed so that CLOSE isn't going on the wire but closed internally.
> 
> > Also, given the name and the pairing with nfs42_ssc_open(), would it be
> > more logical for it to do the fput() as well?
> 
> I'd like to keep that fput() in the nfsd to make it consistent with
> the "intra". There are fput()s for intra but intra doesn't call into
> nfs42_ssc_close().

OK, I think.

I'll need an ACK from Trond and/or Anna on this one in any case.

--b.
Olga Kornievskaia Nov. 1, 2018, 8:30 p.m. UTC | #4
On Thu, Nov 1, 2018 at 4:13 PM J. Bruce Fields <bfields@fieldses.org> wrote:
>
> On Wed, Oct 31, 2018 at 02:54:51PM -0400, Olga Kornievskaia wrote:
> > On Wed, Oct 31, 2018 at 2:40 PM J. Bruce Fields <bfields@fieldses.org> wrote:
> > >
> > > Just to pick one thing that I don't understand yet:
> > >
> > > On Fri, Oct 19, 2018 at 11:28:56AM -0400, Olga Kornievskaia wrote:
> > > > +EXPORT_SYMBOL_GPL(nfs42_ssc_open);
> > > > +void nfs42_ssc_close(struct file *filep)
> > > > +{
> > > > +     struct nfs_open_context *ctx = nfs_file_open_context(filep);
> > > > +
> > > > +     ctx->state->flags = 0;
> > >
> > > Why is this needed?
> >
> > This is needed so that CLOSE isn't going on the wire but closed internally.
> >
> > > Also, given the name and the pairing with nfs42_ssc_open(), would it be
> > > more logical for it to do the fput() as well?
> >
> > I'd like to keep that fput() in the nfsd to make it consistent with
> > the "intra". There are fput()s for intra but intra doesn't call into
> > nfs42_ssc_close().
>
> OK, I think.
>
> I'll need an ACK from Trond and/or Anna on this one in any case.

I included the client-side patches only so that you can compile and
run (or at least I tried as later I think I realized that you needed
one more patch. Thus I have asked if you are planning to run just
include all the client-side series). But I have submitted all of them
to be reviewed as client-side patches. Thus they have been reviewed by
Anna (don't know if Trond is looking of not) and some by others
(Jeff).
diff mbox series

Patch

diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 8d59c96..f229864 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -307,6 +307,13 @@  extern int nfs4_set_rw_stateid(nfs4_stateid *stateid,
 		const struct nfs_open_context *ctx,
 		const struct nfs_lock_context *l_ctx,
 		fmode_t fmode);
+extern int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+			     struct nfs_fattr *fattr, struct nfs4_label *label,
+			     struct inode *inode);
+extern int update_open_stateid(struct nfs4_state *state,
+				const nfs4_stateid *open_stateid,
+				const nfs4_stateid *deleg_stateid,
+				fmode_t fmode);
 
 #if defined(CONFIG_NFS_V4_1)
 extern int nfs41_sequence_done(struct rpc_task *, struct nfs4_sequence_res *);
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index 4288a6e..f82cb05 100644
--- a/fs/nfs/nfs4file.c
+++ b/fs/nfs/nfs4file.c
@@ -8,6 +8,7 @@ 
 #include <linux/file.h>
 #include <linux/falloc.h>
 #include <linux/nfs_fs.h>
+#include <linux/file.h>
 #include "delegation.h"
 #include "internal.h"
 #include "iostat.h"
@@ -242,6 +243,103 @@  static int nfs42_clone_file_range(struct file *src_file, loff_t src_off,
 out:
 	return ret;
 }
+
+static int read_name_gen = 1;
+#define SSC_READ_NAME_BODY "ssc_read_%d"
+
+struct file *
+nfs42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh,
+		nfs4_stateid *stateid)
+{
+	struct nfs_fattr fattr;
+	struct file *filep, *res;
+	struct nfs_server *server;
+	struct inode *r_ino = NULL;
+	struct nfs_open_context *ctx;
+	struct nfs4_state_owner *sp;
+	char *read_name;
+	int len, status = 0;
+
+	server = NFS_SERVER(ss_mnt->mnt_root->d_inode);
+
+	nfs_fattr_init(&fattr);
+
+	status = nfs4_proc_getattr(server, src_fh, &fattr, NULL, NULL);
+	if (status < 0) {
+		res = ERR_PTR(status);
+		goto out;
+	}
+
+	res = ERR_PTR(-ENOMEM);
+	len = strlen(SSC_READ_NAME_BODY) + 16;
+	read_name = kzalloc(len, GFP_NOFS);
+	if (read_name == NULL)
+		goto out;
+	snprintf(read_name, len, SSC_READ_NAME_BODY, read_name_gen++);
+	dprintk("%s read_name %s\n", __func__, read_name);
+
+	r_ino = nfs_fhget(ss_mnt->mnt_root->d_inode->i_sb, src_fh, &fattr,
+			NULL);
+	if (IS_ERR(r_ino)) {
+		res = ERR_CAST(r_ino);
+		goto out;
+	}
+
+	filep = alloc_file_pseudo(r_ino, ss_mnt, read_name, FMODE_READ,
+				     r_ino->i_fop);
+	if (IS_ERR(filep)) {
+		res = ERR_CAST(filep);
+		goto out;
+	}
+	filep->f_mode |= FMODE_READ;
+
+	ctx = alloc_nfs_open_context(filep->f_path.dentry, filep->f_mode,
+					filep);
+	if (IS_ERR(ctx)) {
+		res = ERR_CAST(ctx);
+		goto out_filep;
+	}
+
+	res = ERR_PTR(-EINVAL);
+	sp = nfs4_get_state_owner(server, ctx->cred, GFP_KERNEL);
+	if (sp == NULL)
+		goto out_ctx;
+
+	ctx->state = nfs4_get_open_state(r_ino, sp);
+	if (ctx->state == NULL)
+		goto out_stateowner;
+
+	set_bit(NFS_OPEN_STATE, &ctx->state->flags);
+	memcpy(&ctx->state->open_stateid.other, &stateid->other,
+	       NFS4_STATEID_OTHER_SIZE);
+	update_open_stateid(ctx->state, stateid, NULL, filep->f_mode);
+
+	nfs_file_set_open_context(filep, ctx);
+	put_nfs_open_context(ctx);
+
+	file_ra_state_init(&filep->f_ra, filep->f_mapping->host->i_mapping);
+	res = filep;
+out:
+	dprintk("<-- %s error %ld filep %p r_ino %p\n",
+		__func__, IS_ERR(res) ? PTR_ERR(res) : 0, res, r_ino);
+
+	return res;
+out_stateowner:
+	nfs4_put_state_owner(sp);
+out_ctx:
+	put_nfs_open_context(ctx);
+out_filep:
+	fput(filep);
+	goto out;
+}
+EXPORT_SYMBOL_GPL(nfs42_ssc_open);
+void nfs42_ssc_close(struct file *filep)
+{
+	struct nfs_open_context *ctx = nfs_file_open_context(filep);
+
+	ctx->state->flags = 0;
+}
+EXPORT_SYMBOL_GPL(nfs42_ssc_close);
 #endif /* CONFIG_NFS_V4_2 */
 
 const struct file_operations nfs4_file_operations = {
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index db84b4a..1876456 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -91,7 +91,6 @@ 
 static int _nfs4_recover_proc_open(struct nfs4_opendata *data);
 static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
 static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr);
-static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label, struct inode *inode);
 static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label, struct inode *inode);
 static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
 			    struct nfs_fattr *fattr, struct iattr *sattr,
@@ -1653,7 +1652,7 @@  static void nfs_state_clear_delegation(struct nfs4_state *state)
 	write_sequnlock(&state->seqlock);
 }
 
-static int update_open_stateid(struct nfs4_state *state,
+int update_open_stateid(struct nfs4_state *state,
 		const nfs4_stateid *open_stateid,
 		const nfs4_stateid *delegation,
 		fmode_t fmode)
@@ -3936,7 +3935,7 @@  static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 	return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
 }
 
-static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
+int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle,
 				struct nfs_fattr *fattr, struct nfs4_label *label,
 				struct inode *inode)
 {