diff mbox series

[v6,05/19] NFS: inter ssc open

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

Commit Message

Olga Kornievskaia Sept. 6, 2019, 7:46 p.m. UTC
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: Olga Kornievskaia <kolga@netapp.com>
Signed-off-by: Andy Adamson <andros@netapp.com>
---
 fs/nfs/nfs4_fs.h  |  7 +++++
 fs/nfs/nfs4file.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/nfs/nfs4proc.c |  5 ++-
 3 files changed, 103 insertions(+), 3 deletions(-)

Comments

J. Bruce Fields Sept. 12, 2019, 8:23 p.m. UTC | #1
On Fri, Sep 06, 2019 at 03:46:17PM -0400, Olga Kornievskaia wrote:
> +static int read_name_gen = 1;
> +#define SSC_READ_NAME_BODY "ssc_read_%d"
> +
...
> +	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++);
...
> +	filep = alloc_file_pseudo(r_ino, ss_mnt, read_name, FMODE_READ,
> +				     r_ino->i_fop);

So, I"m curious: does this "name" ever get used anywhere?  Can you see
it from userspace somehow, for example?  Does it have some debugging
value?  Or could it just be the empty string?

--b.
Olga Kornievskaia Sept. 12, 2019, 10:51 p.m. UTC | #2
On Thu, Sep 12, 2019 at 4:23 PM J. Bruce Fields <bfields@fieldses.org> wrote:
>
> On Fri, Sep 06, 2019 at 03:46:17PM -0400, Olga Kornievskaia wrote:
> > +static int read_name_gen = 1;
> > +#define SSC_READ_NAME_BODY "ssc_read_%d"
> > +
> ...
> > +     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++);
> ...
> > +     filep = alloc_file_pseudo(r_ino, ss_mnt, read_name, FMODE_READ,
> > +                                  r_ino->i_fop);
>
> So, I"m curious: does this "name" ever get used anywhere?  Can you see
> it from userspace somehow, for example?  Does it have some debugging
> value?  Or could it just be the empty string?

Name isn't seen anywhere (nor is the mount visible to the use -- ie
doing a mount command). It's needed to create a file structure to
represent the file opened the source server (without the open).
Honestly, I'm not sure what kind of weirdness can arise from having an
empty name string. Is there a reason for not trying to generate unique
names for this?

>
> --b.
J. Bruce Fields Sept. 13, 2019, 12:29 a.m. UTC | #3
On Thu, Sep 12, 2019 at 06:51:58PM -0400, Olga Kornievskaia wrote:
> On Thu, Sep 12, 2019 at 4:23 PM J. Bruce Fields <bfields@fieldses.org> wrote:
> >
> > On Fri, Sep 06, 2019 at 03:46:17PM -0400, Olga Kornievskaia wrote:
> > > +static int read_name_gen = 1;
> > > +#define SSC_READ_NAME_BODY "ssc_read_%d"
> > > +
> > ...
> > > +     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++);
> > ...
> > > +     filep = alloc_file_pseudo(r_ino, ss_mnt, read_name, FMODE_READ,
> > > +                                  r_ino->i_fop);
> >
> > So, I"m curious: does this "name" ever get used anywhere?  Can you see
> > it from userspace somehow, for example?  Does it have some debugging
> > value?  Or could it just be the empty string?
> 
> Name isn't seen anywhere (nor is the mount visible to the use -- ie
> doing a mount command). It's needed to create a file structure to
> represent the file opened the source server (without the open).
> Honestly, I'm not sure what kind of weirdness can arise from having an
> empty name string.

I doubt the name matters.

> Is there a reason for not trying to generate unique
> names for this?

I doubt it's a problem, really, just a little unnecessary code.

--b.
diff mbox series

Patch

diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 8e590b4..5f27942 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -311,6 +311,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);
 
 extern int nfs4_proc_get_lease_time(struct nfs_client *clp,
 		struct nfs_fsinfo *fsinfo);
diff --git a/fs/nfs/nfs4file.c b/fs/nfs/nfs4file.c
index b68b41b..1898262a 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"
@@ -286,6 +287,99 @@  static loff_t nfs42_remap_file_range(struct file *src_file, loff_t src_off,
 out:
 	return ret < 0 ? ret : count;
 }
+
+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++);
+
+	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:
+	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 5311def..7ea446b 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, const struct cred *cred,
 			    struct nfs_fattr *fattr, struct iattr *sattr,
@@ -1713,7 +1712,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)
@@ -4026,7 +4025,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)
 {