From: bfields@fieldses.org (J. Bruce Fields)
To: Olga Kornievskaia <kolga@netapp.com>
Cc: Trond.Myklebust@primarydata.com, anna.schumaker@netapp.com,
bfields@redhat.com, linux-nfs@vger.kernel.org
Subject: Re: [RFC v3 28/42] NFSD add nfs4 inter ssc to nfsd4_copy
Date: Fri, 8 Sep 2017 16:28:13 -0400 [thread overview]
Message-ID: <20170908202813.GC18220@fieldses.org> (raw)
In-Reply-To: <20170711164416.1982-29-kolga@netapp.com>
On Tue, Jul 11, 2017 at 12:44:02PM -0400, Olga Kornievskaia wrote:
> Given a universal address, mount the source server from the destination
> server. Use an internal mount. Call the NFS client nfs42_ssc_open to
> obtain the NFS struct file suitable for nfsd_copy_range.
>
> Add Kconfig dependencies for inter server to server copy
>
> Signed-off-by: Andy Adamson <andros@netapp.com>
> ---
> fs/nfsd/Kconfig | 10 ++
> fs/nfsd/nfs4proc.c | 262 +++++++++++++++++++++++++++++++++++++++++++++++++--
> include/linux/nfs4.h | 1 +
> 3 files changed, 263 insertions(+), 10 deletions(-)
>
> diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
> index 20b1c17..37ff3d5 100644
> --- a/fs/nfsd/Kconfig
> +++ b/fs/nfsd/Kconfig
> @@ -131,6 +131,16 @@ config NFSD_FLEXFILELAYOUT
>
> If unsure, say N.
>
> +config NFSD_V4_2_INTER_SSC
> + bool "NFSv4.2 inter server to server COPY"
> + depends on NFSD_V4 && NFS_V4_1 && NFS_V4_2
> + help
> + This option enables support for NFSv4.2 inter server to
> + server copy where the destination server calls the NFSv4.2
> + client to read the data to copy from the source server.
> +
> + If unsure, say N.
> +
> config NFSD_V4_SECURITY_LABEL
> bool "Provide Security Label support for NFSv4 server"
> depends on NFSD_V4 && SECURITY
> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
> index ceee852..b1095e9 100644
> --- a/fs/nfsd/nfs4proc.c
> +++ b/fs/nfsd/nfs4proc.c
> @@ -1072,16 +1072,227 @@ static int fill_in_write_vector(struct kvec *vec, struct nfsd4_write *write)
> return status;
> }
>
> +#ifdef CONFIG_NFSD_V4_2_INTER_SSC
> +
> +extern struct file *nfs42_ssc_open(struct vfsmount *ss_mnt,
> + struct nfs_fh *src_fh,
> + nfs4_stateid *stateid);
> +extern struct file *nfs42_ssc_close(struct file *filep);
> +
> +extern void nfs_sb_deactive(struct super_block *sb);
> +
> +#define NFSD42_INTERSSC_RAWDATA "minorversion=2,vers=4,addr=%s,clientaddr=%s"
INTERSCC_RAWDATA isn't the most helpful name. Maybe MOUNTOPTS could be
in there?
> +
> +/**
> + * Support one copy source server for now.
> + */
> +static struct vfsmount *
> +nfsd4_interssc_connect(struct nl4_servers *nss, struct svc_rqst *rqstp)
> +{
> + struct file_system_type *type;
> + struct vfsmount *ss_mnt;
> + struct nfs42_netaddr *naddr;
> + struct sockaddr_storage tmp_addr;
> + size_t tmp_addrlen, match_netid_len = 3;
> + char *startsep = "", *endsep = "", *match_netid = "tcp";
> + char *ipaddr, *ipaddr2, *raw_data;
> + int len, raw_len, status = -EINVAL;
> +
> + /* Currently support for one NL4_NETADDR source server */
> + if (nss->nl_svr->nl4_type != NL4_NETADDR) {
> + WARN(nss->nl_svr->nl4_type != NL4_NETADDR,
> + "nfsd4_copy src server not NL4_NETADDR\n");
> + goto out_err;
> + }
We already checked this at xdr decoding time, didn't we? Well, maybe
i'ts still worth a WARN. Better, as mentioned before, maybe the data
structures just should assume only 1 NL4_NETADDR source server.
> +
> + naddr = &nss->nl_svr->u.nl4_addr;
> +
> + tmp_addrlen = rpc_uaddr2sockaddr(SVC_NET(rqstp), naddr->na_uaddr,
> + naddr->na_uaddr_len,
> + (struct sockaddr *)&tmp_addr,
> + sizeof(tmp_addr));
> + if (tmp_addrlen == 0)
> + goto out_err;
> +
> + if (tmp_addr.ss_family == AF_INET6) {
> + startsep = "[";
> + endsep = "]";
> + match_netid = "tcp6";
> + match_netid_len = 4;
> + }
What about the tcp/ipv4 case? Oh, I see, it's handled by the
initialization above. That's a little confusing.
> +
> + if (naddr->na_netid_len != match_netid_len ||
> + strncmp(naddr->na_netid, match_netid, naddr->na_netid_len))
> + goto out_err;
> +
> + /* Construct the raw data for the vfs_kern_mount call */
> + len = RPC_MAX_ADDRBUFLEN + 1;
> + ipaddr = kzalloc(len, GFP_KERNEL);
> + if (!ipaddr)
> + goto out_err;
> +
> + rpc_ntop((struct sockaddr *)&tmp_addr, ipaddr, len);
> +
> + /* 2 for ipv6 endsep and startsep. 3 for ":/" and trailing '/0'*/
> + ipaddr2 = kzalloc(len + 5, GFP_KERNEL);
> + if (!ipaddr2)
> + goto out_free_ipaddr;
> +
> + rpc_ntop((struct sockaddr *)&rqstp->rq_daddr, ipaddr2, len + 5);
> +
> + raw_len = strlen(NFSD42_INTERSSC_RAWDATA) + strlen(ipaddr) +
> + strlen(ipaddr2);
> + raw_data = kzalloc(raw_len, GFP_KERNEL);
> + if (!raw_data)
> + goto out_free_ipaddr2;
> +
> + snprintf(raw_data, raw_len, NFSD42_INTERSSC_RAWDATA, ipaddr,
> + ipaddr2);
Could "raw_data" be named more helpfully?
> +
> + status = -ENODEV;
> + type = get_fs_type("nfs");
> + if (!type)
> + goto out_free_rawdata;
> +
> + /* Set the server:<export> for the vfs_kerne_mount call */
> + memset(ipaddr2, 0, len + 5);
> + snprintf(ipaddr2, len + 5, "%s%s%s:/", startsep, ipaddr, endsep);
> +
> + dprintk("%s Raw mount data: %s server:export %s\n", __func__,
> + raw_data, ipaddr2);
> +
> + /* Use an 'internal' mount: MS_KERNMOUNT -> MNT_INTERNAL */
> + ss_mnt = vfs_kern_mount(type, MS_KERNMOUNT, ipaddr2, raw_data);
I wonder if creating a mount (even a kernel internal one) has any
unexpected side effects. Is it a problem that it could share caches
with any already-existing mounts of that export?
> + if (IS_ERR(ss_mnt)) {
> + status = PTR_ERR(ss_mnt);
> + goto out_free_rawdata;
> + }
> +
> + kfree(raw_data);
> + kfree(ipaddr2);
> + kfree(ipaddr);
> +
> + return ss_mnt;
> +
> +out_free_rawdata:
> + kfree(raw_data);
> +out_free_ipaddr2:
> + kfree(ipaddr2);
> +out_free_ipaddr:
> + kfree(ipaddr);
> +out_err:
> + dprintk("--> %s ERROR %d\n", __func__, status);
> + return ERR_PTR(status);
> +}
> +
> +static void
> +nfsd4_interssc_disconnect(struct vfsmount *ss_mnt)
> +{
> + mntput(ss_mnt);
> + nfs_sb_deactive(ss_mnt->mnt_sb);
OK, I don't claim to understand that.
Are you sure it's still safe to dereference ss_mnt after calling
mntput() on it?
> +}
> +
> +/**
> + * nfsd4_setup_inter_ssc
> + *
> + * Verify COPY destination stateid.
> + * Connect to the source server with NFSv4.1.
> + * Create the source struct file for nfsd_copy_range.
> + * Called with COPY cstate:
> + * SAVED_FH: source filehandle
> + * CURRENT_FH: destination filehandle
> + *
> + * Returns errno (not nfserrxxx)
> + */
> +static struct vfsmount *
> +nfsd4_setup_inter_ssc(struct svc_rqst *rqstp,
> + struct nfsd4_compound_state *cstate,
> + struct nfsd4_copy *copy, struct file **src,
> + struct file **dst)
> +{
> + struct svc_fh *s_fh = NULL;
> + stateid_t *s_stid = ©->cp_src_stateid;
> + struct nfs_fh fh;
> + nfs4_stateid stateid;
> + struct file *filp;
> + struct vfsmount *ss_mnt;
> + __be32 status;
> +
> + /* Verify the destination stateid and set dst struct file*/
> + status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
> + ©->cp_dst_stateid,
> + WR_STATE, dst, NULL);
> + if (status) {
> + ss_mnt = ERR_PTR(be32_to_cpu(status));
> + goto out;
> + }
> +
> + /* Inter copy source fh is always stale */
Not necessarily.
> + CLEAR_CSTATE_FLAG(cstate, IS_STALE_FH);
> +
> + ss_mnt = nfsd4_interssc_connect(©->cp_src, rqstp);
> + if (IS_ERR(ss_mnt))
> + goto out;
> +
> + s_fh = &cstate->save_fh;
> +
> + fh.size = s_fh->fh_handle.fh_size;
> + memcpy(fh.data, &s_fh->fh_handle.fh_base, fh.size);
> + stateid.seqid = s_stid->si_generation;
> + memcpy(stateid.other, (void *)&s_stid->si_opaque,
> + sizeof(stateid_opaque_t));
> +
> + filp = nfs42_ssc_open(ss_mnt, &fh, &stateid);
So that was defined in the client-side patches?
> + if (IS_ERR(filp)) {
> + nfsd4_interssc_disconnect(ss_mnt);
> + return ERR_CAST(filp);
> + }
> + *src = filp;
> +out:
> + return ss_mnt;
> +}
> +
> +static void
> +nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct file *src,
> + struct file *dst)
> +{
> + nfs42_ssc_close(src);
> + fput(src);
> + fput(dst);
> +
> + nfsd4_interssc_disconnect(ss_mnt);
> +
> +}
> +
> +#else /* CONFIG_NFSD_V4_2_INTER_SSC */
> +
> +static struct vfsmount *
> +nfsd4_setup_inter_ssc(struct svc_rqst *rqstp,
> + struct nfsd4_compound_state *cstate,
> + struct nfsd4_copy *copy, struct file **src,
> + struct file **dst)
> +{
> + return ERR_PTR(-EINVAL);
> +}
> +
> +static void
> +nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct file *src,
> + struct file *dst)
> +{
> +}
> +
> +#endif /* CONFIG_NFSD_V4_2_INTER_SSC */
> +
> static __be32
> -nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> - struct nfsd4_copy *copy)
> +nfsd4_setup_intra_ssc(struct svc_rqst *rqstp,
> + struct nfsd4_compound_state *cstate,
> + struct nfsd4_copy *copy, struct file **src,
> + struct file **dst)
> {
> - struct file *src, *dst;
> __be32 status;
> - ssize_t bytes;
>
> - status = nfsd4_verify_copy(rqstp, cstate, ©->cp_src_stateid, &src,
> - ©->cp_dst_stateid, &dst);
> + status = nfsd4_verify_copy(rqstp, cstate, ©->cp_src_stateid, src,
> + ©->cp_dst_stateid, dst);
> if (status)
> goto out;
>
> @@ -1089,7 +1300,37 @@ static int fill_in_write_vector(struct kvec *vec, struct nfsd4_write *write)
> if (HAS_CSTATE_FLAG(cstate, IS_STALE_FH)) {
> CLEAR_CSTATE_FLAG(cstate, IS_STALE_FH);
> cstate->status = nfserr_copy_stalefh;
> - goto out_put;
> + }
> +out:
> + return status;
> +}
> +
> +static void
> +nfsd4_cleanup_intra_ssc(struct file *src, struct file *dst)
> +{
> + fput(src);
> + fput(dst);
> +}
> +
> +static __be32
> +nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> + struct nfsd4_copy *copy)
> +{
> + struct vfsmount *ss_mnt = NULL;
> + struct file *src, *dst;
> + __be32 status;
> + ssize_t bytes;
> +
> + if (copy->cp_src.nl_nsvr > 0) { /* Inter server SSC */
> + ss_mnt = nfsd4_setup_inter_ssc(rqstp, cstate, copy, &src, &dst);
> + if (IS_ERR(ss_mnt)) {
> + status = nfserrno(PTR_ERR(ss_mnt));
> + goto out;
Touched on before, I think: this could use some checking to make sure
that the error returned is useful to the client. (I'm not sure exactly
what the most likely failures are, though.)
--b.
> + }
> + } else {
> + status = nfsd4_setup_intra_ssc(rqstp, cstate, copy, &src, &dst);
> + if (status)
> + goto out;
> }
>
> bytes = nfsd_copy_file_range(src, copy->cp_src_pos,
> @@ -1106,9 +1347,10 @@ static int fill_in_write_vector(struct kvec *vec, struct nfsd4_write *write)
> status = nfs_ok;
> }
>
> -out_put:
> - fput(src);
> - fput(dst);
> + if (copy->cp_src.nl_nsvr > 0) /* Inter server SSC */
> + nfsd4_cleanup_inter_ssc(ss_mnt, src, dst);
> + else
> + nfsd4_cleanup_intra_ssc(src, dst);
> out:
> return status;
> }
> diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h
> index 5aa36ac..843443b 100644
> --- a/include/linux/nfs4.h
> +++ b/include/linux/nfs4.h
> @@ -16,6 +16,7 @@
> #include <linux/uidgid.h>
> #include <uapi/linux/nfs4.h>
> #include <linux/sunrpc/msg_prot.h>
> +#include <linux/nfs.h>
>
> enum nfs4_acl_whotype {
> NFS4_ACL_WHO_NAMED = 0,
> --
> 1.8.3.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2017-09-08 20:28 UTC|newest]
Thread overview: 81+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-07-11 16:43 [PATCH v3 00/42] NFS/NFSD support for async and inter COPY Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 01/42] fs: Don't copy beyond the end of the file Olga Kornievskaia
2017-07-11 18:39 ` Anna Schumaker
2017-07-11 16:43 ` [RFC v3 02/42] VFS permit cross device vfs_copy_file_range Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 03/42] NFS CB_OFFLOAD xdr Olga Kornievskaia
2017-07-11 20:27 ` Anna Schumaker
2017-07-11 16:43 ` [RFC v3 04/42] NFS OFFLOAD_STATUS xdr Olga Kornievskaia
2017-07-11 21:01 ` Anna Schumaker
2017-07-12 17:23 ` Olga Kornievskaia
2017-07-12 17:25 ` Anna Schumaker
2017-07-11 16:43 ` [RFC v3 05/42] NFS OFFLOAD_STATUS op Olga Kornievskaia
2017-07-12 12:41 ` Anna Schumaker
2017-07-11 16:43 ` [RFC v3 06/42] NFS OFFLOAD_CANCEL xdr Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 07/42] NFS COPY xdr handle async reply Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 08/42] NFS add support for asynchronous COPY Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 09/42] NFS handle COPY reply CB_OFFLOAD call race Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 10/42] NFS export nfs4_async_handle_error Olga Kornievskaia
2017-07-12 13:56 ` Anna Schumaker
2017-07-12 17:18 ` Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 11/42] NFS test for intra vs inter COPY Olga Kornievskaia
2017-07-12 14:06 ` Anna Schumaker
2017-07-12 17:21 ` Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 12/42] NFS send OFFLOAD_CANCEL when COPY killed Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 13/42] NFS handle COPY ERR_OFFLOAD_NO_REQS Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 14/42] NFS if we got partial copy ignore errors Olga Kornievskaia
2017-07-12 14:52 ` Anna Schumaker
2017-07-12 17:19 ` Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 15/42] NFS recover from destination server reboot for copies Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 16/42] NFS NFSD defining nl4_servers structure needed by both Olga Kornievskaia
2017-09-06 20:35 ` J. Bruce Fields
2017-09-08 20:51 ` Olga Kornievskaia
2017-09-11 16:22 ` J. Bruce Fields
2017-07-11 16:43 ` [RFC v3 17/42] NFS add COPY_NOTIFY operation Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 18/42] NFS add ca_source_server<> to COPY Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 19/42] NFS also send OFFLOAD_CANCEL to source server Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 20/42] NFS inter ssc open Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 21/42] NFS skip recovery of copy open on dest server Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 22/42] NFS for "inter" copy treat ESTALE as ENOTSUPP Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 23/42] NFS add a simple sync nfs4_proc_commit after async COPY Olga Kornievskaia
2017-07-12 17:13 ` Anna Schumaker
2017-07-12 17:18 ` Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 24/42] NFSD add ca_source_server<> to COPY Olga Kornievskaia
2017-07-11 16:43 ` [RFC v3 25/42] NFSD add COPY_NOTIFY operation Olga Kornievskaia
2017-09-06 20:45 ` J. Bruce Fields
2017-09-13 14:39 ` Olga Kornievskaia
2017-09-06 21:34 ` J. Bruce Fields
2017-09-13 14:38 ` Olga Kornievskaia
2017-09-06 21:37 ` J. Bruce Fields
2017-09-13 14:38 ` Olga Kornievskaia
2017-09-13 14:42 ` J. Bruce Fields
2017-07-11 16:44 ` [RFC v3 26/42] NFSD generalize nfsd4_compound_state flag names Olga Kornievskaia
2017-07-11 16:44 ` [RFC v3 27/42] NFSD: allow inter server COPY to have a STALE source server fh Olga Kornievskaia
2017-09-08 19:38 ` J. Bruce Fields
2017-09-08 19:52 ` Olga Kornievskaia
2017-09-08 19:57 ` J. Bruce Fields
2017-09-08 20:09 ` Olga Kornievskaia
2017-09-14 18:44 ` Olga Kornievskaia
2017-09-15 1:47 ` J. Bruce Fields
2017-09-15 19:46 ` Olga Kornievskaia
2017-09-15 20:02 ` J. Bruce Fields
2017-09-15 20:06 ` J. Bruce Fields
2017-09-15 20:11 ` Olga Kornievskaia
2017-09-16 14:44 ` J. Bruce Fields
2017-07-11 16:44 ` [RFC v3 28/42] NFSD add nfs4 inter ssc to nfsd4_copy Olga Kornievskaia
2017-09-08 20:28 ` J. Bruce Fields [this message]
2017-07-11 16:44 ` [RFC v3 29/42] NFSD return nfs4_stid in nfs4_preprocess_stateid_op Olga Kornievskaia
2017-07-11 16:44 ` [RFC v3 30/42] NFSD Unique stateid_t for inter server to server COPY authentication Olga Kornievskaia
2017-07-11 16:44 ` [RFC v3 31/42] NFSD CB_OFFLOAD xdr Olga Kornievskaia
2017-07-11 16:44 ` [RFC v3 32/42] NFSD OFFLOAD_STATUS xdr Olga Kornievskaia
2017-07-12 19:39 ` Anna Schumaker
2017-07-11 16:44 ` [RFC v3 33/42] NFSD OFFLOAD_CANCEL xdr Olga Kornievskaia
2017-07-11 16:44 ` [RFC v3 34/42] NFSD xdr callback stateid in async COPY reply Olga Kornievskaia
2017-07-11 16:44 ` [RFC v3 35/42] NFSD first draft of async copy Olga Kornievskaia
2017-07-12 20:29 ` Anna Schumaker
2017-07-11 16:44 ` [RFC v3 36/42] NFSD handle OFFLOAD_CANCEL op Olga Kornievskaia
2017-07-11 16:44 ` [RFC v3 37/42] NFSD stop queued async copies on client shutdown Olga Kornievskaia
2017-07-11 16:44 ` [RFC v3 38/42] NFSD create new stateid for async copy Olga Kornievskaia
2017-07-11 16:44 ` [RFC v3 39/42] NFSD define EBADF in nfserrno Olga Kornievskaia
2017-07-11 16:44 ` [RFC v3 40/42] NFSD support OFFLOAD_STATUS Olga Kornievskaia
2017-07-11 16:44 ` [RFC v3 41/42] NFSD remove copy stateid when vfs_copy_file_range completes Olga Kornievskaia
2017-07-11 16:44 ` [RFC v3 42/42] NFSD delay the umount after COPY Olga Kornievskaia
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170908202813.GC18220@fieldses.org \
--to=bfields@fieldses.org \
--cc=Trond.Myklebust@primarydata.com \
--cc=anna.schumaker@netapp.com \
--cc=bfields@redhat.com \
--cc=kolga@netapp.com \
--cc=linux-nfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).