On Tue, Oct 23, 2018 at 4:23 PM Schumaker, Anna <Anna.Schumaker@xxxxxxxxxx> wrote: > > Hi Olga, > > On Fri, 2018-10-19 at 11:29 -0400, Olga Kornievskaia wrote: > > From: Olga Kornievskaia <kolga@xxxxxxxxxx> > > > > 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@xxxxxxxxxx> > > Signed-off-by: Olga Kornievskaia <kolga@xxxxxxxxxx> > > --- > > fs/nfs/nfs4_fs.h | 7 ++++ > > fs/nfs/nfs4file.c | 98 > > +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > > fs/nfs/nfs4proc.c | 5 ++- > > 3 files changed, 107 insertions(+), 3 deletions(-) > > > > 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 005862e..7f226f4 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" > > @@ -264,6 +265,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); > > Does this dprintk() need to be here? Nope, doesn't need to be here, a left over debugging. I'll remove it. > I'm wondering if it would work better as a > tracepoint (or if it should just be removed altogether). > > Thanks, > Anna > > > + > > + 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 fec6e6b..e5178b2f 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) > > {