RE: [pnfs] [RFC 14/39] nfs41: Implement NFSv4.1 callback service process.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> -----Original Message-----
> From: Myklebust, Trond
> Sent: Thursday, June 04, 2009 1:18 PM
> To: Benny Halevy
> Cc: linux-nfs@xxxxxxxxxxxxxxx; pnfs@xxxxxxxxxxxxx
> Subject: Re: [pnfs] [RFC 14/39] nfs41: Implement NFSv4.1 callback
service
> process.
> 
> On Fri, 2009-05-01 at 02:21 +0300, Benny Halevy wrote:
> > From: Ricardo Labiaga <Ricardo.Labiaga@xxxxxxxxxx>
> >
> > nfs41_callback_up() initializes the necessary queues and creates the
new
> > nfs41_callback_svc thread.  This thread executes the callback
service
> which
> > waits for requests to arrive on the svc_serv->sv_cb_list.
> >
> > NFS41_BC_MIN_CALLBACKS is set to 1 because we expect callbacks to
not
> > cause substantial latency.
> >
> > The actual processing of the callback will be implemented as a
separate
> patch.
> >
> > There is only one NFSv4.1 callback service.  The first caller of
> > nfs4_callback_up() creates the service, subsequent callers increment
a
> > reference count on the service.  The service is destroyed when the
last
> > caller invokes nfs_callback_down().
> >
> > The transport needs to hold a reference to the callback service in
order
> > to invoke it during callback processing.  Currently this reference
is
> only
> > obtained when the service is first created.  This is incorrect,
since
> > subsequent registrations for other transports will leave the
xprt->serv
> > pointer uninitialized, leading to an oops when a callback arrives on
> > the "unreferenced" transport.
> >
> > This patch fixes the problem by ensuring that a reference to the
service
> > is saved in xprt->serv, either because the service is created by
this
> > invocation to nfs4_callback_up() or by a prior invocation.
> >
> > Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@xxxxxxxxxx>
> > Signed-off-by: Benny Halevy <bhalevy@xxxxxxxxxxx>
> > [nfs41: Add a reference to svc_serv during callback service bring
up]
> > Signed-off-by: Ricardo Labiaga <Ricardo.Labiaga@xxxxxxxxxx>
> > Signed-off-by: Benny Halevy <bhalevy@xxxxxxxxxxx>
> > ---
> >  fs/nfs/callback.c          |   83
> ++++++++++++++++++++++++++++++++++++++++++-
> >  fs/nfs/callback.h          |    7 ++++
> >  include/linux/sunrpc/svc.h |    2 +
> >  3 files changed, 90 insertions(+), 2 deletions(-)
> >
> > diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
> > index 3926046..9ee174c 100644
> > --- a/fs/nfs/callback.c
> > +++ b/fs/nfs/callback.c
> > @@ -17,6 +17,9 @@
> >  #include <linux/freezer.h>
> >  #include <linux/kthread.h>
> >  #include <linux/sunrpc/svcauth_gss.h>
> > +#if defined(CONFIG_NFS_V4_1)
> > +#include <linux/sunrpc/bc_xprt.h>
> > +#endif
> >
> >  #include <net/inet_sock.h>
> >
> > @@ -131,6 +134,69 @@ out_err:
> >  	return ERR_PTR(ret);
> >  }
> >
> > +#if defined(CONFIG_NFS_V4_1)
> > +/*
> > + * The callback service for NFSv4.1 callbacks
> > + */
> > +static int
> > +nfs41_callback_svc(void *vrqstp)
> > +{
> > +	struct svc_rqst *rqstp = vrqstp;
> > +	struct svc_serv *serv = rqstp->rq_server;
> > +	struct rpc_rqst *req;
> > +	int error;
> > +	DEFINE_WAIT(wq);
> > +
> > +	set_freezable();
> > +
> > +	/*
> > +	 * FIXME: do we really need to run this under the BKL? If so,
please
> > +	 * add a comment about what it's intended to protect.
> > +	 */
> > +	lock_kernel();
> > +	while (!kthread_should_stop()) {
> > +		prepare_to_wait(&serv->sv_cb_waitq, &wq,
TASK_INTERRUPTIBLE);
> > +		spin_lock_bh(&serv->sv_cb_lock);
> > +		if (!list_empty(&serv->sv_cb_list)) {
> > +			req = list_first_entry(&serv->sv_cb_list,
> > +					struct rpc_rqst, rq_bc_list);
> > +			list_del(&req->rq_bc_list);
> > +			spin_unlock_bh(&serv->sv_cb_lock);
> > +			dprintk("Invoking bc_svc_process()\n");
> > +			error = bc_svc_process(serv, req, rqstp);
> > +			dprintk("bc_svc_process() returned w/ error
code= %d\n",
> > +				error);
> > +		} else {
> > +			spin_unlock_bh(&serv->sv_cb_lock);
> > +			schedule();
> > +		}
> > +		finish_wait(&serv->sv_cb_waitq, &wq);
> > +	}
> > +	unlock_kernel();
> > +	nfs_callback_info.task = NULL;
> > +	svc_exit_thread(rqstp);
> > +	return 0;
> > +}
> > +
> > +/*
> > + * Bring up the NFSv4.1 callback service
> > + */
> > +struct svc_rqst *
> > +nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt)
> > +{
> > +	/*
> > +	 * Save the svc_serv in the transport so that it can
> > +	 * be referenced when the session backchannel is initialized
> > +	 */
> > +	xprt->bc_serv = serv;
> > +
> > +	INIT_LIST_HEAD(&serv->sv_cb_list);
> > +	spin_lock_init(&serv->sv_cb_lock);
> > +	init_waitqueue_head(&serv->sv_cb_waitq);
> > +	return svc_prepare_thread(serv, &serv->sv_pools[0]);
> > +}
> > +#endif /* CONFIG_NFS_V4_1 */
> > +
> >  /*
> >   * Bring up the callback thread if it is not already up.
> >   */
> > @@ -141,10 +207,18 @@ int nfs_callback_up(u32 minorversion, void
*args)
> >  	int (*callback_svc)(void *vrqstp);
> >  	char svc_name[12];
> >  	int ret = 0;
> > +#if defined(CONFIG_NFS_V4_1)
> > +	struct rpc_xprt *xprt = (struct rpc_xprt *)args;
> > +#endif /* CONFIG_NFS_V4_1 */
> 
> More ugly embedded ifdefs...
> 
> >
> >  	mutex_lock(&nfs_callback_mutex);
> > -	if (nfs_callback_info.users++ || nfs_callback_info.task != NULL)
> > +	if (nfs_callback_info.users++ || nfs_callback_info.task != NULL)
{
> > +#if defined(CONFIG_NFS_V4_1)
> > +		if (minorversion)
> > +			xprt->bc_serv = nfs_callback_info.serv;
> > +#endif /* CONFIG_NFS_V4_1 */
> 
> Ditto
> 
> >  		goto out;
> > +	}
> >  	serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE,
> NULL);
> >  	if (!serv) {
> >  		ret = -ENOMEM;
> > @@ -157,7 +231,12 @@ int nfs_callback_up(u32 minorversion, void
*args)
> >  		rqstp = nfs4_callback_up(serv);
> >  		callback_svc = nfs4_callback_svc;
> >  	} else {
> > -		BUG();	/* for now */
> > +#if defined(CONFIG_NFS_V4_1)
> > +		rqstp = nfs41_callback_up(serv, xprt);
> > +		callback_svc = nfs41_callback_svc;
> > +#else  /* CONFIG_NFS_V4_1 */
> > +		BUG();
> > +#endif /* CONFIG_NFS_V4_1 */
> 
> Ditto
> 
> >  	}
> >
> >  	if (IS_ERR(rqstp)) {
> > diff --git a/fs/nfs/callback.h b/fs/nfs/callback.h
> > index 7f12e65..f2696ba 100644
> > --- a/fs/nfs/callback.h
> > +++ b/fs/nfs/callback.h
> > @@ -70,6 +70,13 @@ extern void nfs_callback_down(void);
> >  #define nfs_callback_down()	do {} while(0)
> >  #endif
> >
> > +/*
> > + * nfs41: Callbacks are expected to not cause substantial latency,
> > + * so we limit their concurrency to 1 by setting up the maximum
number
> > + * of slots for the backchannel.
> > + */
> > +#define NFS41_BC_MIN_CALLBACKS 1
> > +
> >  extern unsigned int nfs_callback_set_tcpport;
> >  extern unsigned short nfs_callback_tcpport;
> >  extern unsigned short nfs_callback_tcpport6;
> > diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
> > index 4a8afbd..16043c4 100644
> > --- a/include/linux/sunrpc/svc.h
> > +++ b/include/linux/sunrpc/svc.h
> > @@ -419,6 +419,8 @@ int		   svc_set_num_threads(struct
svc_serv
> *, struct svc_pool *, int);
> >  int		   svc_pool_stats_open(struct svc_serv *serv,
struct file
> *file);
> >  void		   svc_destroy(struct svc_serv *);
> >  int		   svc_process(struct svc_rqst *);
> > +int		   bc_svc_process(struct svc_serv *, struct
rpc_rqst *,
> > +			struct svc_rqst *);
> 
> OK, I give up. Why is the function text and export declaration in one
> patch, while the declaration is in this patch?
> 

Will move this declaration to patch 13 along with the function and
export declaration.  Will also address the ifdefs.

- ricardo

> >  int		   svc_register(const struct svc_serv *, const
int,
> >  				const unsigned short, const unsigned
short);
> >
> 
> --
> Trond Myklebust
> Linux NFS client maintainer
> 
> NetApp
> Trond.Myklebust@xxxxxxxxxx
> www.netapp.com
> _______________________________________________
> pNFS mailing list
> pNFS@xxxxxxxxxxxxx
> http://linux-nfs.org/cgi-bin/mailman/listinfo/pnfs
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux