[pnfs] [PATCH 1/2] nfs41: Add a reference to svc_serv during callback service bring up
Labiaga, Ricardo
Ricardo.Labiaga at netapp.com
Wed Mar 5 18:21:44 EST 2008
> -----Original Message-----
> From: Benny Halevy [mailto:bhalevy at panasas.com]
> Sent: Tuesday, March 04, 2008 11:53 PM
> To: Labiaga, Ricardo
> Cc: pnfs at linux-nfs.org
> Subject: Re: [pnfs] [PATCH 1/2] nfs41: Add a reference to
> svc_serv during callback service bring up
>
> Ricardo Labiaga wrote:
> > From: Ricardo Labiaga <Ricardo.Labiaga at netapp.com>
> >
> > 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 at netapp.com>
> > ---
> > fs/nfs/callback.c | 22 ++++++++++++++++------
> > 1 files changed, 16 insertions(+), 6 deletions(-)
> >
> > diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
> > index e6a55a6..4afd42c 100644
> > --- a/fs/nfs/callback.c
> > +++ b/fs/nfs/callback.c
> > @@ -186,12 +186,6 @@ int nfs4_callback_up(struct svc_serv *serv)
> > */
> > int 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->serv = serv;
> > -
>
> The xprt parameter is no longer used and can be removed.
True, will remove it.
> > INIT_LIST_HEAD(&serv->sv_cb_list);
> > spin_lock_init(&serv->sv_cb_lock);
> > init_waitqueue_head(&serv->sv_cb_waitq);
> > @@ -236,6 +230,22 @@ int nfs_callback_up(int minorversion,
> void *args)
> > nfs_callback_info.serv = serv;
> > wait_for_completion(&nfs_callback_info.started);
> > out:
> > + if (ret == 0) {
> > + switch (minorversion) {
>
> The surrounding logic seem to be a bit overly complex for a
> single statement
> that needs to be done for minorversion 1. How about a simple
> if () statement
> rather than the switch?
I'm just being consistent with the rest of the minorversion switching in
other places. I guess we're preparing for v4.2 :-) We use the switch
pretty much everywhere. One advantage of using the switch statement is
that it "flags" the places that are minorversion aware - for future
maintenance. Having said that, I don't really feel strong about it
either way.
>
> > + case 0:
> > + break;
> > +#if defined(CONFIG_NFS_V4_1)
> > + case 1:
> > + /*
> > + * Save the svc_serv in the transport
> so that it can
> > + * be referenced when the session backchannel is
> > + * initialized and when callbacks arrive.
> > + */
> > + xprt->serv = nfs_callback_info.serv;
> > + break;
> > +#endif /* CONFIG_NFS_V4_1 */
> > + }
> > + }
>
> Also, you can define a new label here, say "out_common:", to
> be gone to
> from the out_err path rather than goto out to save "if (ret) { }"
>
> > mutex_unlock(&nfs_callback_mutex);
> > unlock_kernel();
> > return ret;
>
> BTW, looking at this function I don't see how it's supposed
> to work when mounting
> over both minor versions. We call either
> nfs4{,1}_callback_up first time around
> and the other is never called after the callback service is created.
> This needs to be re-written so we can bring either both
> threads up and down
> together or independently on-demand maybe by having two
> copies of nfs_callback_info,
> one for each minor version. In which case I think they can
> share the service
> which is created once in nfs_callback_up and never destroyed.
My bad, thanks for catching this. I'll resubmit a fixed version.
>
> One more todo item, while I'm at it is to replace the void
> *args argument
> to nfs_callback_up() with struct rpc_xprt *xprt since it's
> always passed
> by nfs4_init_client()
Okay.
- ricardo
>
> Benny
>
More information about the pNFS
mailing list