All of lore.kernel.org
 help / color / mirror / Atom feed
From: "J. Bruce Fields" <bfields@fieldses.org>
To: Anna Schumaker <bjschuma@netapp.com>
Cc: linux-nfs@vger.kernel.org
Subject: Re: [RFC 5/4] NFSD: Add basic CB_OFFLOAD support
Date: Mon, 28 Oct 2013 17:52:21 -0400	[thread overview]
Message-ID: <20131028215221.GQ31322@fieldses.org> (raw)
In-Reply-To: <1382972247-1108-6-git-send-email-bjschuma@netapp.com>

On Mon, Oct 28, 2013 at 10:57:27AM -0400, Anna Schumaker wrote:
> This patch adds basic offload support to the WRITE_PLUS operation.
> Since I don't implement OFFLOAD_ABORT, OFFLOAD_REVOKE or OFFLOAD_STATUS
> this patch is NOT spec compliant and should not be applied without
> further work.

Ugh.  I don't understand why we need asynchronous modes for all these
operations.

--b.

> 
> I'm including this patch to show how I handled offloading to test client
> code.
> ---
>  fs/nfsd/nfs4callback.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++
>  fs/nfsd/nfs4proc.c     |  56 ++++++++++++++++++---
>  fs/nfsd/nfs4state.c    |  11 +++++
>  fs/nfsd/state.h        |   4 ++
>  fs/nfsd/xdr4.h         |  14 ++++++
>  fs/nfsd/xdr4cb.h       |   9 ++++
>  6 files changed, 219 insertions(+), 7 deletions(-)
> 
> diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
> index 7f05cd1..1f6c150 100644
> --- a/fs/nfsd/nfs4callback.c
> +++ b/fs/nfsd/nfs4callback.c
> @@ -35,6 +35,7 @@
>  #include <linux/sunrpc/svc_xprt.h>
>  #include <linux/slab.h>
>  #include "nfsd.h"
> +#include "xdr4.h"
>  #include "state.h"
>  #include "netns.h"
>  #include "xdr4cb.h"
> @@ -52,6 +53,9 @@ enum {
>  	NFSPROC4_CLNT_CB_NULL = 0,
>  	NFSPROC4_CLNT_CB_RECALL,
>  	NFSPROC4_CLNT_CB_SEQUENCE,
> +
> +	/* NFS v4.2 callback */
> +	NFSPROC4_CLNT_CB_OFFLOAD,
>  };
>  
>  struct nfs4_cb_compound_hdr {
> @@ -110,6 +114,7 @@ enum nfs_cb_opnum4 {
>  	OP_CB_WANTS_CANCELLED		= 12,
>  	OP_CB_NOTIFY_LOCK		= 13,
>  	OP_CB_NOTIFY_DEVICEID		= 14,
> +	OP_CB_OFFLOAD			= 15,
>  	OP_CB_ILLEGAL			= 10044
>  };
>  
> @@ -469,6 +474,31 @@ out_default:
>  	return nfs_cb_stat_to_errno(nfserr);
>  }
>  
> +static void encode_cb_offload4args(struct xdr_stream *xdr,
> +				   const struct nfsd4_cb_offload *offload,
> +				   struct nfs4_cb_compound_hdr *hdr)
> +{
> +	__be32 *p;
> +
> +	if (hdr->minorversion < 2)
> +		return;
> +
> +	encode_nfs_cb_opnum4(xdr, OP_CB_OFFLOAD);
> +	encode_nfs_fh4(xdr, &offload->co_fh);
> +	encode_stateid4(xdr, &offload->co_res.wr_stid->sc_stateid);
> +
> +	p = xdr_reserve_space(xdr, 4);
> +	*p = cpu_to_be32(1);
> +	encode_stateid4(xdr, &offload->co_res.wr_stid->sc_stateid);
> +
> +	p = xdr_reserve_space(xdr, 12 + NFS4_VERIFIER_SIZE);
> +	p = xdr_encode_hyper(p, offload->co_res.wr_bytes_written);
> +	*p++ = cpu_to_be32(offload->co_res.wr_stable_how);
> +	xdr_encode_opaque_fixed(p, offload->co_res.wr_verifier.data, NFS4_VERIFIER_SIZE);
> +
> +	hdr->nops++;
> +}
> +
>  /*
>   * NFSv4.0 and NFSv4.1 XDR encode functions
>   *
> @@ -505,6 +535,23 @@ static void nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, struct xdr_stream *xdr,
>  	encode_cb_nops(&hdr);
>  }
>  
> +/*
> + * CB_OFFLOAD
> + */
> +static void nfs4_xdr_enc_cb_offload(struct rpc_rqst *req, struct xdr_stream *xdr,
> +				    const struct nfsd4_callback *cb)
> +{
> +	const struct nfsd4_cb_offload *args = cb->cb_op;
> +	struct nfs4_cb_compound_hdr hdr = {
> +		.ident = cb->cb_clp->cl_cb_ident,
> +		.minorversion = cb->cb_minorversion,
> +	};
> +
> +	encode_cb_compound4args(xdr, &hdr);
> +	encode_cb_sequence4args(xdr, cb, &hdr);
> +	encode_cb_offload4args(xdr, args, &hdr);
> +	encode_cb_nops(&hdr);
> +}
>  
>  /*
>   * NFSv4.0 and NFSv4.1 XDR decode functions
> @@ -552,6 +599,36 @@ out:
>  }
>  
>  /*
> + * CB_OFFLOAD
> + */
> +static int nfs4_xdr_dec_cb_offload(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
> +				   struct nfsd4_callback *cb)
> +{
> +	struct nfs4_cb_compound_hdr hdr;
> +	enum nfsstat4 nfserr;
> +	int status;
> +
> +	status = decode_cb_compound4res(xdr, &hdr);
> +	if (unlikely(status))
> +		goto out;
> +
> +	if (cb != NULL) {
> +		status = decode_cb_sequence4res(xdr, cb);
> +		if (unlikely(status))
> +			goto out;
> +	}
> +
> +	status = decode_cb_op_status(xdr, OP_CB_OFFLOAD, &nfserr);
> +	if (unlikely(status))
> +		goto out;
> +	if (unlikely(nfserr != NFS4_OK))
> +		status = nfs_cb_stat_to_errno(nfserr);
> +
> +out:
> +	return status;
> +}
> +
> +/*
>   * RPC procedure tables
>   */
>  #define PROC(proc, call, argtype, restype)				\
> @@ -568,6 +645,7 @@ out:
>  static struct rpc_procinfo nfs4_cb_procedures[] = {
>  	PROC(CB_NULL,	NULL,		cb_null,	cb_null),
>  	PROC(CB_RECALL,	COMPOUND,	cb_recall,	cb_recall),
> +	PROC(CB_OFFLOAD, COMPOUND,	cb_offload,	cb_offload),
>  };
>  
>  static struct rpc_version nfs_cb_version4 = {
> @@ -1036,3 +1114,57 @@ void nfsd4_cb_recall(struct nfs4_delegation *dp)
>  
>  	run_nfsd4_cb(&dp->dl_recall);
>  }
> +
> +static void nfsd4_cb_offload_done(struct rpc_task *task, void *calldata)
> +{
> +	struct nfsd4_callback *cb = calldata;
> +	struct nfs4_client *clp = cb->cb_clp;
> +	struct rpc_clnt *current_rpc_client = clp->cl_cb_client;
> +
> +	nfsd4_cb_done(task, calldata);
> +
> +	if (current_rpc_client != task->tk_client)
> +		return;
> +
> +	if (cb->cb_done)
> +		return;
> +
> +	if (task->tk_status != 0)
> +		nfsd4_mark_cb_down(clp, task->tk_status);
> +	cb->cb_done = true;
> +}
> +
> +static void nfsd4_cb_offload_release(void *calldata)
> +{
> +	struct nfsd4_callback *cb = calldata;
> +	struct nfsd4_cb_offload *offload = container_of(cb, struct nfsd4_cb_offload, co_callback);
> +
> +	if (cb->cb_done) {
> +		nfs4_free_offload_stateid(offload->co_res.wr_stid);
> +		kfree(offload);
> +	}
> +}
> +
> +static const struct rpc_call_ops nfsd4_cb_offload_ops = {
> +	.rpc_call_prepare = nfsd4_cb_prepare,
> +	.rpc_call_done    = nfsd4_cb_offload_done,
> +	.rpc_release      = nfsd4_cb_offload_release,
> +};
> +
> +void nfsd4_cb_offload(struct nfsd4_cb_offload *offload)
> +{
> +	struct nfsd4_callback *cb = &offload->co_callback;
> +
> +	cb->cb_op = offload;
> +	cb->cb_clp = offload->co_res.wr_stid->sc_client;
> +	cb->cb_msg.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_OFFLOAD];
> +	cb->cb_msg.rpc_argp = cb;
> +	cb->cb_msg.rpc_resp = cb;
> +
> +	cb->cb_ops = &nfsd4_cb_offload_ops;
> +
> +	INIT_LIST_HEAD(&cb->cb_per_client);
> +	cb->cb_done = true;
> +
> +	run_nfsd4_cb(cb);
> +}
> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
> index bc45ed2..d56f7fe 100644
> --- a/fs/nfsd/nfs4proc.c
> +++ b/fs/nfsd/nfs4proc.c
> @@ -1028,22 +1028,64 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
>  	return status;
>  }
>  
> -static __be32
> -nfsd4_write_plus_hole(struct file *file, struct nfsd4_write_plus *writeplus,
> -		      struct net *net)
> +static void
> +nfsd4_offload_work(struct nfsd4_cb_offload *offload,
> +		   struct nfsd4_compound_state *cstate,
> +		   struct nfsd42_write_res *write_res,
> +		   void (*offload_func)(struct work_struct *))
> +{
> +	offload->co_res.wr_stid = nfs4_alloc_offload_stateid(cstate->session->se_client);
> +	memcpy(&offload->co_fh, &cstate->current_fh, sizeof(struct knfsd_fh));
> +
> +	write_res->wr_stid = offload->co_res.wr_stid;
> +	write_res->wr_bytes_written = 0;
> +	write_res->wr_stable_how = NFS_UNSTABLE;
> +
> +	nfsd4_init_callback(&offload->co_callback);
> +	INIT_WORK(&offload->co_work, offload_func);
> +	schedule_work(&offload->co_work);
> +}
> +
> +static void
> +nfsd4_write_plus_hole_async(struct work_struct *work)
>  {
> +	struct nfsd4_cb_offload *offload;
> +	struct nfsd4_write_plus *writeplus;
>  	__be32 status;
>  
> -	status = nfsd4_vfs_fallocate(file, writeplus->wp_allocated,
> +	offload = container_of(work, struct nfsd4_cb_offload, co_work);
> +	writeplus = &offload->co_u.write_plus;
> +
> +	status = nfsd4_vfs_fallocate(offload->co_file, writeplus->wp_allocated,
>  				writeplus->wp_offset, writeplus->wp_length);
>  	if (status == nfs_ok) {
>  		writeplus->wp_res.wr_stid = NULL;
>  		writeplus->wp_res.wr_bytes_written = writeplus->wp_length;
>  		writeplus->wp_res.wr_stable_how = NFS_FILE_SYNC;
> -		gen_boot_verifier(&writeplus->wp_res.wr_verifier, net);
> +		gen_boot_verifier(&writeplus->wp_res.wr_verifier, offload->co_net);
>  	}
>  
> -	return status;
> +	fput(offload->co_file);
> +	nfsd4_cb_offload(offload);
> +}
> +
> +static __be32
> +nfsd4_write_plus_hole(struct file *file, struct nfsd4_write_plus *writeplus,
> +		      struct nfsd4_compound_state *cstate, struct net *net)
> +{
> +	struct nfsd4_cb_offload *offload;
> +
> +	offload = kmalloc(sizeof(struct nfsd4_cb_offload), GFP_KERNEL);
> +	if (!offload)
> +		return nfserrno(PTR_ERR(offload));
> +
> +	memcpy(&offload->co_u.write_plus, writeplus, sizeof(struct nfsd4_write_plus));
> +	offload->co_file = get_file(file);
> +	offload->co_net  = net;
> +
> +	nfsd4_offload_work(offload, cstate, &writeplus->wp_res, nfsd4_write_plus_hole_async);
> +
> +	return 0;
>  }
>  
>  static __be32
> @@ -1060,7 +1102,7 @@ nfsd4_write_plus(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
>  		return status;
>  
>  	if (writeplus->wp_data_content == NFS4_CONTENT_HOLE)
> -		return nfsd4_write_plus_hole(file, writeplus, net);
> +		return nfsd4_write_plus_hole(file, writeplus, cstate, net);
>  	return nfserr_union_notsupp;
>  }
>  
> diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
> index 0874998..6342167 100644
> --- a/fs/nfsd/nfs4state.c
> +++ b/fs/nfsd/nfs4state.c
> @@ -364,6 +364,11 @@ static struct nfs4_ol_stateid * nfs4_alloc_stateid(struct nfs4_client *clp)
>  	return openlockstateid(nfs4_alloc_stid(clp, stateid_slab));
>  }
>  
> +struct nfs4_stid *nfs4_alloc_offload_stateid(struct nfs4_client *clp)
> +{
> +	return nfs4_alloc_stid(clp, stateid_slab);
> +}
> +
>  static struct nfs4_delegation *
>  alloc_init_deleg(struct nfs4_client *clp, struct nfs4_ol_stateid *stp, struct svc_fh *current_fh)
>  {
> @@ -613,6 +618,12 @@ static void free_generic_stateid(struct nfs4_ol_stateid *stp)
>  	kmem_cache_free(stateid_slab, stp);
>  }
>  
> +void nfs4_free_offload_stateid(struct nfs4_stid *stid)
> +{
> +	remove_stid(stid);
> +	kmem_cache_free(stateid_slab, stid);
> +}
> +
>  static void release_lock_stateid(struct nfs4_ol_stateid *stp)
>  {
>  	struct file *file;
> diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
> index 424d8f5..a40d29a 100644
> --- a/fs/nfsd/state.h
> +++ b/fs/nfsd/state.h
> @@ -452,6 +452,7 @@ static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s)
>  #define WR_STATE	        0x00000020
>  
>  struct nfsd4_compound_state;
> +struct nfsd4_cb_offload;
>  struct nfsd_net;
>  
>  extern __be32 nfs4_preprocess_stateid_op(struct net *net,
> @@ -472,6 +473,7 @@ extern void nfsd4_probe_callback(struct nfs4_client *clp);
>  extern void nfsd4_probe_callback_sync(struct nfs4_client *clp);
>  extern void nfsd4_change_callback(struct nfs4_client *clp, struct nfs4_cb_conn *);
>  extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
> +extern void nfsd4_cb_offload(struct nfsd4_cb_offload *);
>  extern int nfsd4_create_callback_queue(void);
>  extern void nfsd4_destroy_callback_queue(void);
>  extern void nfsd4_shutdown_callback(struct nfs4_client *);
> @@ -480,6 +482,8 @@ extern struct nfs4_client_reclaim *nfs4_client_to_reclaim(const char *name,
>  							struct nfsd_net *nn);
>  extern bool nfs4_has_reclaimed_state(const char *name, struct nfsd_net *nn);
>  extern void put_client_renew(struct nfs4_client *clp);
> +extern struct nfs4_stid *nfs4_alloc_offload_stateid(struct nfs4_client *);
> +extern void nfs4_free_offload_stateid(struct nfs4_stid *);
>  
>  /* nfs4recover operations */
>  extern int nfsd4_client_tracking_init(struct net *net);
> diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
> index ae9debc..24e2c07 100644
> --- a/fs/nfsd/xdr4.h
> +++ b/fs/nfsd/xdr4.h
> @@ -451,6 +451,20 @@ struct nfsd4_write_plus {
>  	struct nfsd42_write_res	wp_res;
>  };
>  
> +struct nfsd4_cb_offload {
> +	union {
> +		struct nfsd4_write_plus write_plus;
> +	} co_u;
> +
> +	struct knfsd_fh		co_fh;
> +	struct file		*co_file;
> +	struct net		*co_net;
> +
> +	struct nfsd42_write_res	co_res;
> +	struct work_struct	co_work;
> +	struct nfsd4_callback	co_callback;
> +};
> +
>  struct nfsd4_seek {
>  	/* request */
>  	stateid_t	seek_stateid;
> diff --git a/fs/nfsd/xdr4cb.h b/fs/nfsd/xdr4cb.h
> index c5c55df..75b0ef7 100644
> --- a/fs/nfsd/xdr4cb.h
> +++ b/fs/nfsd/xdr4cb.h
> @@ -21,3 +21,12 @@
>  #define NFS4_dec_cb_recall_sz		(cb_compound_dec_hdr_sz  +      \
>  					cb_sequence_dec_sz +            \
>  					op_dec_sz)
> +
> +#define NFS4_enc_cb_offload_sz		(cb_compound_enc_hdr_sz +      \
> +					 cb_sequence_enc_sz +          \
> +					 1 + enc_stateid_sz + 2 + 1 +  \
> +					 XDR_QUADLEN(NFS4_VERIFIER_SIZE))
> +
> +#define NFS4_dec_cb_offload_sz		(cb_compound_dec_hdr_sz +  \
> +					 cb_sequence_dec_sz +      \
> +					 op_dec_sz)
> -- 
> 1.8.4.1
> 

  reply	other threads:[~2013-10-28 21:52 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-10-28 14:57 [PATCH 0/4] NFSD: Add support for WRITE_PLUS and SEEK Anna Schumaker
2013-10-28 14:57 ` [PATCH 1/4] NFSD: Update error codes Anna Schumaker
2013-10-28 14:57 ` [PATCH 2/4] NFSD: Create nfs v4.2 decode ops Anna Schumaker
2013-10-28 20:54   ` J. Bruce Fields
2013-10-28 20:59     ` Myklebust, Trond
2013-10-28 21:11       ` J. Bruce Fields
2013-10-29 12:43         ` Anna Schumaker
2013-10-29 13:33           ` J. Bruce Fields
2013-10-28 14:57 ` [PATCH 3/4] NFSD: Add WRITE_PLUS support for hole punches Anna Schumaker
2013-10-28 21:40   ` J. Bruce Fields
2013-10-29 12:49     ` Anna Schumaker
2013-10-29 13:34       ` J. Bruce Fields
2013-10-29 12:50     ` Anna Schumaker
2013-10-29 13:06       ` J. Bruce Fields
2013-10-29 13:11         ` Anna Schumaker
2013-10-29 13:23         ` Myklebust, Trond
2013-10-29 13:28           ` Anna Schumaker
2013-10-29 13:32           ` Dr Fields James Bruce
2013-11-02 13:54         ` Christoph Hellwig
2013-11-02 14:44           ` J. Bruce Fields
2013-11-02 14:51             ` Christoph Hellwig
2013-11-02 15:02               ` Myklebust, Trond
2013-11-02 15:07                 ` Christoph Hellwig
2013-11-02 15:20     ` Christoph Hellwig
2013-11-02 13:52   ` Christoph Hellwig
2013-11-04 16:41     ` Anna Schumaker
2013-11-04 17:03       ` Christoph Hellwig
2013-11-04 17:23         ` Anna Schumaker
2013-11-04 18:53           ` Christoph Hellwig
2013-11-04 18:57             ` Anna Schumaker
2013-11-04 19:16             ` Chuck Lever
2013-11-04 19:19               ` Christoph Hellwig
2013-11-04 19:50                 ` Chuck Lever
2013-11-04 19:54                   ` Christoph Hellwig
2013-11-04 19:55                   ` J. Bruce Fields
2013-11-04 20:03                   ` Haynes, Tom
2013-11-04 20:13                     ` Christoph Hellwig
2013-11-05  9:40   ` Christoph Hellwig
2013-11-05 14:23     ` Anna Schumaker
2013-11-05 15:11       ` Christoph Hellwig
2013-10-28 14:57 ` [PATCH 4/4] NFSD: Implement SEEK Anna Schumaker
2013-10-28 21:51   ` J. Bruce Fields
2013-10-29 12:53     ` Anna Schumaker
2013-10-29  7:35   ` Christoph Hellwig
2013-10-29 13:00     ` Anna Schumaker
2013-10-29 13:07       ` Christoph Hellwig
2013-10-29 13:30         ` J. Bruce Fields
2013-11-02 13:48           ` Christoph Hellwig
2013-11-02 14:37             ` J. Bruce Fields
2013-11-02 14:41               ` Christoph Hellwig
2013-11-04 16:46                 ` J. Bruce Fields
2013-11-04 17:05                   ` Christoph Hellwig
2013-11-04 17:22                     ` Chuck Lever
2013-11-05 12:33                       ` Christoph Hellwig
2013-11-04 21:56                   ` Thomas Haynes
2013-11-05  1:03                     ` Christoph Hellwig
2013-11-05  2:07                       ` Haynes, Tom
2013-11-05  8:23                         ` Christoph Hellwig
2013-10-31 16:04   ` Christoph Hellwig
2013-10-31 16:07     ` Anna Schumaker
2013-10-31 16:17     ` Anna Schumaker
2013-10-31 17:13       ` Christoph Hellwig
2013-10-28 14:57 ` [RFC 5/4] NFSD: Add basic CB_OFFLOAD support Anna Schumaker
2013-10-28 21:52   ` J. Bruce Fields [this message]
2013-10-29  7:37     ` Christoph Hellwig
2013-10-29 13:36       ` J. Bruce Fields
2013-10-29 13:38         ` Christoph Hellwig
2013-10-29 13:53           ` J. Bruce Fields
2013-10-29 15:11             ` Christoph Hellwig
2013-10-28 20:00 ` [PATCH 0/4] NFSD: Add support for WRITE_PLUS and SEEK Christoph Hellwig

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=20131028215221.GQ31322@fieldses.org \
    --to=bfields@fieldses.org \
    --cc=bjschuma@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.