Re: [RFC PATCH 5 3/7] nfsd - use service thread if not executing in init namespace

2015-04-02 Thread J. Bruce Fields
On Wed, Apr 01, 2015 at 08:22:58AM +0800, Ian Kent wrote:
> On Tue, 2015-03-31 at 09:14 -0400, J. Bruce Fields wrote:
> > On Tue, Mar 31, 2015 at 11:14:58AM +0800, Ian Kent wrote:
> > > From: Ian Kent 
> > > 
> > > If nfsd is running within a container the client tracking operations
> > > should run within their originating container also. To do that get a
> > > token to a service thread created within the container environment
> > > for usermode helper calls.
> > > 
> > > Signed-off-by: Ian Kent 
> > > Cc: Benjamin Coddington 
> > > Cc: Al Viro 
> > > Cc: J. Bruce Fields 
> > > Cc: David Howells 
> > > Cc: Trond Myklebust 
> > > Cc: Oleg Nesterov 
> > > Cc: Eric W. Biederman 
> > > Cc: Jeff Layton 
> > > ---
> > >  fs/nfsd/netns.h   |3 +++
> > >  fs/nfsd/nfs4recover.c |   48 
> > > +++-
> > >  fs/nfsd/nfsctl.c  |6 ++
> > >  3 files changed, 40 insertions(+), 17 deletions(-)
> > > 
> > > diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
> > > index ea6749a..099a3c5 100644
> > > --- a/fs/nfsd/netns.h
> > > +++ b/fs/nfsd/netns.h
> > > @@ -112,6 +112,9 @@ struct nfsd_net {
> > >   u32 clientid_counter;
> > >  
> > >   struct svc_serv *nfsd_serv;
> > > +
> > > + /* Namespace token */
> > > + int umh_token;
> > >  };
> > >  
> > >  /* Simple check to find out if a given net was properly initialized */
> > > diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
> > > index 1c307f0..2547edb 100644
> > > --- a/fs/nfsd/nfs4recover.c
> > > +++ b/fs/nfsd/nfs4recover.c
> > > @@ -1184,7 +1184,8 @@ nfsd4_cltrack_grace_start(time_t grace_start)
> > >  }
> > >  
> > >  static int
> > > -nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1)
> > > +nfsd4_umh_cltrack_upcall(char *cmd, char *arg,
> > > +  char *env0, char *env1, int token)
> > >  {
> > >   char *envp[3];
> > >   char *argv[4];
> > > @@ -1209,7 +1210,11 @@ nfsd4_umh_cltrack_upcall(char *cmd, char *arg, 
> > > char *env0, char *env1)
> > >   argv[2] = arg;
> > >   argv[3] = NULL;
> > >  
> > > - ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
> > > + if (token > 0)
> > > + ret = call_usermodehelper_service(argv[0], argv, envp,
> > > +   token, UMH_WAIT_PROC);
> > > + else
> > > + ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
> > 
> > Do we really need to handle the init_net case specially, or could we
> > just let it create a workqueue in that case as well?
> 
> That's pretty much up to you but there's still the need to get a token
> to create the work queue (and put it to terminate it) or just pass 0 to
> call_usermodehelper_service().

Creating a new workqueue in the init_net case would mean inheriting
stuff from the rpc.nfsd environment that we didn't used to.  (But what
stuff exactly?)  So for backwards compatibility reasons perhaps it's
safer to do what you've done even if the result seems a little
inconsistent.

--b.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 5 3/7] nfsd - use service thread if not executing in init namespace

2015-04-02 Thread J. Bruce Fields
On Wed, Apr 01, 2015 at 08:22:58AM +0800, Ian Kent wrote:
 On Tue, 2015-03-31 at 09:14 -0400, J. Bruce Fields wrote:
  On Tue, Mar 31, 2015 at 11:14:58AM +0800, Ian Kent wrote:
   From: Ian Kent ik...@redhat.com
   
   If nfsd is running within a container the client tracking operations
   should run within their originating container also. To do that get a
   token to a service thread created within the container environment
   for usermode helper calls.
   
   Signed-off-by: Ian Kent ik...@redhat.com
   Cc: Benjamin Coddington bcodd...@redhat.com
   Cc: Al Viro v...@zeniv.linux.org.uk
   Cc: J. Bruce Fields bfie...@fieldses.org
   Cc: David Howells dhowe...@redhat.com
   Cc: Trond Myklebust trond.mykleb...@primarydata.com
   Cc: Oleg Nesterov onest...@redhat.com
   Cc: Eric W. Biederman ebied...@xmission.com
   Cc: Jeff Layton jeff.lay...@primarydata.com
   ---
fs/nfsd/netns.h   |3 +++
fs/nfsd/nfs4recover.c |   48 
   +++-
fs/nfsd/nfsctl.c  |6 ++
3 files changed, 40 insertions(+), 17 deletions(-)
   
   diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
   index ea6749a..099a3c5 100644
   --- a/fs/nfsd/netns.h
   +++ b/fs/nfsd/netns.h
   @@ -112,6 +112,9 @@ struct nfsd_net {
 u32 clientid_counter;

 struct svc_serv *nfsd_serv;
   +
   + /* Namespace token */
   + int umh_token;
};

/* Simple check to find out if a given net was properly initialized */
   diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
   index 1c307f0..2547edb 100644
   --- a/fs/nfsd/nfs4recover.c
   +++ b/fs/nfsd/nfs4recover.c
   @@ -1184,7 +1184,8 @@ nfsd4_cltrack_grace_start(time_t grace_start)
}

static int
   -nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1)
   +nfsd4_umh_cltrack_upcall(char *cmd, char *arg,
   +  char *env0, char *env1, int token)
{
 char *envp[3];
 char *argv[4];
   @@ -1209,7 +1210,11 @@ nfsd4_umh_cltrack_upcall(char *cmd, char *arg, 
   char *env0, char *env1)
 argv[2] = arg;
 argv[3] = NULL;

   - ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
   + if (token  0)
   + ret = call_usermodehelper_service(argv[0], argv, envp,
   +   token, UMH_WAIT_PROC);
   + else
   + ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
  
  Do we really need to handle the init_net case specially, or could we
  just let it create a workqueue in that case as well?
 
 That's pretty much up to you but there's still the need to get a token
 to create the work queue (and put it to terminate it) or just pass 0 to
 call_usermodehelper_service().

Creating a new workqueue in the init_net case would mean inheriting
stuff from the rpc.nfsd environment that we didn't used to.  (But what
stuff exactly?)  So for backwards compatibility reasons perhaps it's
safer to do what you've done even if the result seems a little
inconsistent.

--b.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH 5 3/7] nfsd - use service thread if not executing in init namespace

2015-03-31 Thread Ian Kent
On Tue, 2015-03-31 at 09:14 -0400, J. Bruce Fields wrote:
> On Tue, Mar 31, 2015 at 11:14:58AM +0800, Ian Kent wrote:
> > From: Ian Kent 
> > 
> > If nfsd is running within a container the client tracking operations
> > should run within their originating container also. To do that get a
> > token to a service thread created within the container environment
> > for usermode helper calls.
> > 
> > Signed-off-by: Ian Kent 
> > Cc: Benjamin Coddington 
> > Cc: Al Viro 
> > Cc: J. Bruce Fields 
> > Cc: David Howells 
> > Cc: Trond Myklebust 
> > Cc: Oleg Nesterov 
> > Cc: Eric W. Biederman 
> > Cc: Jeff Layton 
> > ---
> >  fs/nfsd/netns.h   |3 +++
> >  fs/nfsd/nfs4recover.c |   48 
> > +++-
> >  fs/nfsd/nfsctl.c  |6 ++
> >  3 files changed, 40 insertions(+), 17 deletions(-)
> > 
> > diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
> > index ea6749a..099a3c5 100644
> > --- a/fs/nfsd/netns.h
> > +++ b/fs/nfsd/netns.h
> > @@ -112,6 +112,9 @@ struct nfsd_net {
> > u32 clientid_counter;
> >  
> > struct svc_serv *nfsd_serv;
> > +
> > +   /* Namespace token */
> > +   int umh_token;
> >  };
> >  
> >  /* Simple check to find out if a given net was properly initialized */
> > diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
> > index 1c307f0..2547edb 100644
> > --- a/fs/nfsd/nfs4recover.c
> > +++ b/fs/nfsd/nfs4recover.c
> > @@ -1184,7 +1184,8 @@ nfsd4_cltrack_grace_start(time_t grace_start)
> >  }
> >  
> >  static int
> > -nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1)
> > +nfsd4_umh_cltrack_upcall(char *cmd, char *arg,
> > +char *env0, char *env1, int token)
> >  {
> > char *envp[3];
> > char *argv[4];
> > @@ -1209,7 +1210,11 @@ nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char 
> > *env0, char *env1)
> > argv[2] = arg;
> > argv[3] = NULL;
> >  
> > -   ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
> > +   if (token > 0)
> > +   ret = call_usermodehelper_service(argv[0], argv, envp,
> > + token, UMH_WAIT_PROC);
> > +   else
> > +   ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
> 
> Do we really need to handle the init_net case specially, or could we
> just let it create a workqueue in that case as well?

That's pretty much up to you but there's still the need to get a token
to create the work queue (and put it to terminate it) or just pass 0 to
call_usermodehelper_service().

> 
> --b.
> 
> > /*
> >  * Disable the upcall mechanism if we're getting an ENOENT or EACCES
> >  * error. The admin can re-enable it on the fly by using sysfs
> > @@ -1252,14 +1257,8 @@ nfsd4_umh_cltrack_init(struct net *net)
> > struct nfsd_net *nn = net_generic(net, nfsd_net_id);
> > char *grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
> >  
> > -   /* XXX: The usermode helper s not working in container yet. */
> > -   if (net != _net) {
> > -   WARN(1, KERN_ERR "NFSD: attempt to initialize umh client "
> > -   "tracking in a container!\n");
> > -   return -EINVAL;
> > -   }
> > -
> > -   ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL);
> > +   ret = nfsd4_umh_cltrack_upcall("init", NULL,
> > +   grace_start, NULL, nn->umh_token);
> > kfree(grace_start);
> > return ret;
> >  }
> > @@ -1285,6 +1284,7 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
> >  {
> > char *hexid, *has_session, *grace_start;
> > struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
> > +   int ret;
> >  
> > /*
> >  * With v4.0 clients, there's little difference in outcome between a
> > @@ -1312,7 +1312,10 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
> > grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
> >  
> > nfsd4_cltrack_upcall_lock(clp);
> > -   if (!nfsd4_umh_cltrack_upcall("create", hexid, has_session, 
> > grace_start))
> > +   ret = nfsd4_umh_cltrack_upcall("create",
> > +  hexid, has_session, grace_start,
> > +  nn->umh_token);
> > +   if (!ret)
> > set_bit(NFSD4_CLIENT_STABLE, >cl_flags);
> > nfsd4_cltrack_upcall_unlock(clp);
> >  
> > @@ -1324,7 +1327,9 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
> >  static void
> >  nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
> >  {
> > +   struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
> > char *hexid;
> > +   int ret;
> >  
> > if (!test_bit(NFSD4_CLIENT_STABLE, >cl_flags))
> > return;
> > @@ -1336,9 +1341,13 @@ nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
> > }
> >  
> > nfsd4_cltrack_upcall_lock(clp);
> > -   if (test_bit(NFSD4_CLIENT_STABLE, >cl_flags) &&
> > -   nfsd4_umh_cltrack_upcall("remove", hexid, NULL, NULL) == 0)
> > -   clear_bit(NFSD4_CLIENT_STABLE, >cl_flags);

Re: [RFC PATCH 5 3/7] nfsd - use service thread if not executing in init namespace

2015-03-31 Thread J. Bruce Fields
On Tue, Mar 31, 2015 at 11:14:58AM +0800, Ian Kent wrote:
> From: Ian Kent 
> 
> If nfsd is running within a container the client tracking operations
> should run within their originating container also. To do that get a
> token to a service thread created within the container environment
> for usermode helper calls.
> 
> Signed-off-by: Ian Kent 
> Cc: Benjamin Coddington 
> Cc: Al Viro 
> Cc: J. Bruce Fields 
> Cc: David Howells 
> Cc: Trond Myklebust 
> Cc: Oleg Nesterov 
> Cc: Eric W. Biederman 
> Cc: Jeff Layton 
> ---
>  fs/nfsd/netns.h   |3 +++
>  fs/nfsd/nfs4recover.c |   48 +++-
>  fs/nfsd/nfsctl.c  |6 ++
>  3 files changed, 40 insertions(+), 17 deletions(-)
> 
> diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
> index ea6749a..099a3c5 100644
> --- a/fs/nfsd/netns.h
> +++ b/fs/nfsd/netns.h
> @@ -112,6 +112,9 @@ struct nfsd_net {
>   u32 clientid_counter;
>  
>   struct svc_serv *nfsd_serv;
> +
> + /* Namespace token */
> + int umh_token;
>  };
>  
>  /* Simple check to find out if a given net was properly initialized */
> diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
> index 1c307f0..2547edb 100644
> --- a/fs/nfsd/nfs4recover.c
> +++ b/fs/nfsd/nfs4recover.c
> @@ -1184,7 +1184,8 @@ nfsd4_cltrack_grace_start(time_t grace_start)
>  }
>  
>  static int
> -nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1)
> +nfsd4_umh_cltrack_upcall(char *cmd, char *arg,
> +  char *env0, char *env1, int token)
>  {
>   char *envp[3];
>   char *argv[4];
> @@ -1209,7 +1210,11 @@ nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char 
> *env0, char *env1)
>   argv[2] = arg;
>   argv[3] = NULL;
>  
> - ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
> + if (token > 0)
> + ret = call_usermodehelper_service(argv[0], argv, envp,
> +   token, UMH_WAIT_PROC);
> + else
> + ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);

Do we really need to handle the init_net case specially, or could we
just let it create a workqueue in that case as well?

--b.

>   /*
>* Disable the upcall mechanism if we're getting an ENOENT or EACCES
>* error. The admin can re-enable it on the fly by using sysfs
> @@ -1252,14 +1257,8 @@ nfsd4_umh_cltrack_init(struct net *net)
>   struct nfsd_net *nn = net_generic(net, nfsd_net_id);
>   char *grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
>  
> - /* XXX: The usermode helper s not working in container yet. */
> - if (net != _net) {
> - WARN(1, KERN_ERR "NFSD: attempt to initialize umh client "
> - "tracking in a container!\n");
> - return -EINVAL;
> - }
> -
> - ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL);
> + ret = nfsd4_umh_cltrack_upcall("init", NULL,
> + grace_start, NULL, nn->umh_token);
>   kfree(grace_start);
>   return ret;
>  }
> @@ -1285,6 +1284,7 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
>  {
>   char *hexid, *has_session, *grace_start;
>   struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
> + int ret;
>  
>   /*
>* With v4.0 clients, there's little difference in outcome between a
> @@ -1312,7 +1312,10 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
>   grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
>  
>   nfsd4_cltrack_upcall_lock(clp);
> - if (!nfsd4_umh_cltrack_upcall("create", hexid, has_session, 
> grace_start))
> + ret = nfsd4_umh_cltrack_upcall("create",
> +hexid, has_session, grace_start,
> +nn->umh_token);
> + if (!ret)
>   set_bit(NFSD4_CLIENT_STABLE, >cl_flags);
>   nfsd4_cltrack_upcall_unlock(clp);
>  
> @@ -1324,7 +1327,9 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
>  static void
>  nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
>  {
> + struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
>   char *hexid;
> + int ret;
>  
>   if (!test_bit(NFSD4_CLIENT_STABLE, >cl_flags))
>   return;
> @@ -1336,9 +1341,13 @@ nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
>   }
>  
>   nfsd4_cltrack_upcall_lock(clp);
> - if (test_bit(NFSD4_CLIENT_STABLE, >cl_flags) &&
> - nfsd4_umh_cltrack_upcall("remove", hexid, NULL, NULL) == 0)
> - clear_bit(NFSD4_CLIENT_STABLE, >cl_flags);
> + if (test_bit(NFSD4_CLIENT_STABLE, >cl_flags)) {
> + ret = nfsd4_umh_cltrack_upcall("remove",
> +hexid, NULL, NULL,
> +nn->umh_token);
> + if (ret == 0)
> + clear_bit(NFSD4_CLIENT_STABLE, >cl_flags);
> + }
>   

Re: [RFC PATCH 5 3/7] nfsd - use service thread if not executing in init namespace

2015-03-31 Thread J. Bruce Fields
On Tue, Mar 31, 2015 at 11:14:58AM +0800, Ian Kent wrote:
 From: Ian Kent ik...@redhat.com
 
 If nfsd is running within a container the client tracking operations
 should run within their originating container also. To do that get a
 token to a service thread created within the container environment
 for usermode helper calls.
 
 Signed-off-by: Ian Kent ik...@redhat.com
 Cc: Benjamin Coddington bcodd...@redhat.com
 Cc: Al Viro v...@zeniv.linux.org.uk
 Cc: J. Bruce Fields bfie...@fieldses.org
 Cc: David Howells dhowe...@redhat.com
 Cc: Trond Myklebust trond.mykleb...@primarydata.com
 Cc: Oleg Nesterov onest...@redhat.com
 Cc: Eric W. Biederman ebied...@xmission.com
 Cc: Jeff Layton jeff.lay...@primarydata.com
 ---
  fs/nfsd/netns.h   |3 +++
  fs/nfsd/nfs4recover.c |   48 +++-
  fs/nfsd/nfsctl.c  |6 ++
  3 files changed, 40 insertions(+), 17 deletions(-)
 
 diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
 index ea6749a..099a3c5 100644
 --- a/fs/nfsd/netns.h
 +++ b/fs/nfsd/netns.h
 @@ -112,6 +112,9 @@ struct nfsd_net {
   u32 clientid_counter;
  
   struct svc_serv *nfsd_serv;
 +
 + /* Namespace token */
 + int umh_token;
  };
  
  /* Simple check to find out if a given net was properly initialized */
 diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
 index 1c307f0..2547edb 100644
 --- a/fs/nfsd/nfs4recover.c
 +++ b/fs/nfsd/nfs4recover.c
 @@ -1184,7 +1184,8 @@ nfsd4_cltrack_grace_start(time_t grace_start)
  }
  
  static int
 -nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1)
 +nfsd4_umh_cltrack_upcall(char *cmd, char *arg,
 +  char *env0, char *env1, int token)
  {
   char *envp[3];
   char *argv[4];
 @@ -1209,7 +1210,11 @@ nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char 
 *env0, char *env1)
   argv[2] = arg;
   argv[3] = NULL;
  
 - ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
 + if (token  0)
 + ret = call_usermodehelper_service(argv[0], argv, envp,
 +   token, UMH_WAIT_PROC);
 + else
 + ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);

Do we really need to handle the init_net case specially, or could we
just let it create a workqueue in that case as well?

--b.

   /*
* Disable the upcall mechanism if we're getting an ENOENT or EACCES
* error. The admin can re-enable it on the fly by using sysfs
 @@ -1252,14 +1257,8 @@ nfsd4_umh_cltrack_init(struct net *net)
   struct nfsd_net *nn = net_generic(net, nfsd_net_id);
   char *grace_start = nfsd4_cltrack_grace_start(nn-boot_time);
  
 - /* XXX: The usermode helper s not working in container yet. */
 - if (net != init_net) {
 - WARN(1, KERN_ERR NFSD: attempt to initialize umh client 
 - tracking in a container!\n);
 - return -EINVAL;
 - }
 -
 - ret = nfsd4_umh_cltrack_upcall(init, NULL, grace_start, NULL);
 + ret = nfsd4_umh_cltrack_upcall(init, NULL,
 + grace_start, NULL, nn-umh_token);
   kfree(grace_start);
   return ret;
  }
 @@ -1285,6 +1284,7 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
  {
   char *hexid, *has_session, *grace_start;
   struct nfsd_net *nn = net_generic(clp-net, nfsd_net_id);
 + int ret;
  
   /*
* With v4.0 clients, there's little difference in outcome between a
 @@ -1312,7 +1312,10 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
   grace_start = nfsd4_cltrack_grace_start(nn-boot_time);
  
   nfsd4_cltrack_upcall_lock(clp);
 - if (!nfsd4_umh_cltrack_upcall(create, hexid, has_session, 
 grace_start))
 + ret = nfsd4_umh_cltrack_upcall(create,
 +hexid, has_session, grace_start,
 +nn-umh_token);
 + if (!ret)
   set_bit(NFSD4_CLIENT_STABLE, clp-cl_flags);
   nfsd4_cltrack_upcall_unlock(clp);
  
 @@ -1324,7 +1327,9 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
  static void
  nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
  {
 + struct nfsd_net *nn = net_generic(clp-net, nfsd_net_id);
   char *hexid;
 + int ret;
  
   if (!test_bit(NFSD4_CLIENT_STABLE, clp-cl_flags))
   return;
 @@ -1336,9 +1341,13 @@ nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
   }
  
   nfsd4_cltrack_upcall_lock(clp);
 - if (test_bit(NFSD4_CLIENT_STABLE, clp-cl_flags) 
 - nfsd4_umh_cltrack_upcall(remove, hexid, NULL, NULL) == 0)
 - clear_bit(NFSD4_CLIENT_STABLE, clp-cl_flags);
 + if (test_bit(NFSD4_CLIENT_STABLE, clp-cl_flags)) {
 + ret = nfsd4_umh_cltrack_upcall(remove,
 +hexid, NULL, NULL,
 +nn-umh_token);
 + if (ret == 0)
 + 

Re: [RFC PATCH 5 3/7] nfsd - use service thread if not executing in init namespace

2015-03-31 Thread Ian Kent
On Tue, 2015-03-31 at 09:14 -0400, J. Bruce Fields wrote:
 On Tue, Mar 31, 2015 at 11:14:58AM +0800, Ian Kent wrote:
  From: Ian Kent ik...@redhat.com
  
  If nfsd is running within a container the client tracking operations
  should run within their originating container also. To do that get a
  token to a service thread created within the container environment
  for usermode helper calls.
  
  Signed-off-by: Ian Kent ik...@redhat.com
  Cc: Benjamin Coddington bcodd...@redhat.com
  Cc: Al Viro v...@zeniv.linux.org.uk
  Cc: J. Bruce Fields bfie...@fieldses.org
  Cc: David Howells dhowe...@redhat.com
  Cc: Trond Myklebust trond.mykleb...@primarydata.com
  Cc: Oleg Nesterov onest...@redhat.com
  Cc: Eric W. Biederman ebied...@xmission.com
  Cc: Jeff Layton jeff.lay...@primarydata.com
  ---
   fs/nfsd/netns.h   |3 +++
   fs/nfsd/nfs4recover.c |   48 
  +++-
   fs/nfsd/nfsctl.c  |6 ++
   3 files changed, 40 insertions(+), 17 deletions(-)
  
  diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
  index ea6749a..099a3c5 100644
  --- a/fs/nfsd/netns.h
  +++ b/fs/nfsd/netns.h
  @@ -112,6 +112,9 @@ struct nfsd_net {
  u32 clientid_counter;
   
  struct svc_serv *nfsd_serv;
  +
  +   /* Namespace token */
  +   int umh_token;
   };
   
   /* Simple check to find out if a given net was properly initialized */
  diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
  index 1c307f0..2547edb 100644
  --- a/fs/nfsd/nfs4recover.c
  +++ b/fs/nfsd/nfs4recover.c
  @@ -1184,7 +1184,8 @@ nfsd4_cltrack_grace_start(time_t grace_start)
   }
   
   static int
  -nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1)
  +nfsd4_umh_cltrack_upcall(char *cmd, char *arg,
  +char *env0, char *env1, int token)
   {
  char *envp[3];
  char *argv[4];
  @@ -1209,7 +1210,11 @@ nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char 
  *env0, char *env1)
  argv[2] = arg;
  argv[3] = NULL;
   
  -   ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
  +   if (token  0)
  +   ret = call_usermodehelper_service(argv[0], argv, envp,
  + token, UMH_WAIT_PROC);
  +   else
  +   ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
 
 Do we really need to handle the init_net case specially, or could we
 just let it create a workqueue in that case as well?

That's pretty much up to you but there's still the need to get a token
to create the work queue (and put it to terminate it) or just pass 0 to
call_usermodehelper_service().

 
 --b.
 
  /*
   * Disable the upcall mechanism if we're getting an ENOENT or EACCES
   * error. The admin can re-enable it on the fly by using sysfs
  @@ -1252,14 +1257,8 @@ nfsd4_umh_cltrack_init(struct net *net)
  struct nfsd_net *nn = net_generic(net, nfsd_net_id);
  char *grace_start = nfsd4_cltrack_grace_start(nn-boot_time);
   
  -   /* XXX: The usermode helper s not working in container yet. */
  -   if (net != init_net) {
  -   WARN(1, KERN_ERR NFSD: attempt to initialize umh client 
  -   tracking in a container!\n);
  -   return -EINVAL;
  -   }
  -
  -   ret = nfsd4_umh_cltrack_upcall(init, NULL, grace_start, NULL);
  +   ret = nfsd4_umh_cltrack_upcall(init, NULL,
  +   grace_start, NULL, nn-umh_token);
  kfree(grace_start);
  return ret;
   }
  @@ -1285,6 +1284,7 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
   {
  char *hexid, *has_session, *grace_start;
  struct nfsd_net *nn = net_generic(clp-net, nfsd_net_id);
  +   int ret;
   
  /*
   * With v4.0 clients, there's little difference in outcome between a
  @@ -1312,7 +1312,10 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
  grace_start = nfsd4_cltrack_grace_start(nn-boot_time);
   
  nfsd4_cltrack_upcall_lock(clp);
  -   if (!nfsd4_umh_cltrack_upcall(create, hexid, has_session, 
  grace_start))
  +   ret = nfsd4_umh_cltrack_upcall(create,
  +  hexid, has_session, grace_start,
  +  nn-umh_token);
  +   if (!ret)
  set_bit(NFSD4_CLIENT_STABLE, clp-cl_flags);
  nfsd4_cltrack_upcall_unlock(clp);
   
  @@ -1324,7 +1327,9 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
   static void
   nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
   {
  +   struct nfsd_net *nn = net_generic(clp-net, nfsd_net_id);
  char *hexid;
  +   int ret;
   
  if (!test_bit(NFSD4_CLIENT_STABLE, clp-cl_flags))
  return;
  @@ -1336,9 +1341,13 @@ nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
  }
   
  nfsd4_cltrack_upcall_lock(clp);
  -   if (test_bit(NFSD4_CLIENT_STABLE, clp-cl_flags) 
  -   nfsd4_umh_cltrack_upcall(remove, hexid, NULL, NULL) == 0)
  -   clear_bit(NFSD4_CLIENT_STABLE, clp-cl_flags);
  +   if (test_bit(NFSD4_CLIENT_STABLE, 

[RFC PATCH 5 3/7] nfsd - use service thread if not executing in init namespace

2015-03-30 Thread Ian Kent
From: Ian Kent 

If nfsd is running within a container the client tracking operations
should run within their originating container also. To do that get a
token to a service thread created within the container environment
for usermode helper calls.

Signed-off-by: Ian Kent 
Cc: Benjamin Coddington 
Cc: Al Viro 
Cc: J. Bruce Fields 
Cc: David Howells 
Cc: Trond Myklebust 
Cc: Oleg Nesterov 
Cc: Eric W. Biederman 
Cc: Jeff Layton 
---
 fs/nfsd/netns.h   |3 +++
 fs/nfsd/nfs4recover.c |   48 +++-
 fs/nfsd/nfsctl.c  |6 ++
 3 files changed, 40 insertions(+), 17 deletions(-)

diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index ea6749a..099a3c5 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -112,6 +112,9 @@ struct nfsd_net {
u32 clientid_counter;
 
struct svc_serv *nfsd_serv;
+
+   /* Namespace token */
+   int umh_token;
 };
 
 /* Simple check to find out if a given net was properly initialized */
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 1c307f0..2547edb 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -1184,7 +1184,8 @@ nfsd4_cltrack_grace_start(time_t grace_start)
 }
 
 static int
-nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1)
+nfsd4_umh_cltrack_upcall(char *cmd, char *arg,
+char *env0, char *env1, int token)
 {
char *envp[3];
char *argv[4];
@@ -1209,7 +1210,11 @@ nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char 
*env0, char *env1)
argv[2] = arg;
argv[3] = NULL;
 
-   ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
+   if (token > 0)
+   ret = call_usermodehelper_service(argv[0], argv, envp,
+ token, UMH_WAIT_PROC);
+   else
+   ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
/*
 * Disable the upcall mechanism if we're getting an ENOENT or EACCES
 * error. The admin can re-enable it on the fly by using sysfs
@@ -1252,14 +1257,8 @@ nfsd4_umh_cltrack_init(struct net *net)
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
char *grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
 
-   /* XXX: The usermode helper s not working in container yet. */
-   if (net != _net) {
-   WARN(1, KERN_ERR "NFSD: attempt to initialize umh client "
-   "tracking in a container!\n");
-   return -EINVAL;
-   }
-
-   ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL);
+   ret = nfsd4_umh_cltrack_upcall("init", NULL,
+   grace_start, NULL, nn->umh_token);
kfree(grace_start);
return ret;
 }
@@ -1285,6 +1284,7 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
 {
char *hexid, *has_session, *grace_start;
struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
+   int ret;
 
/*
 * With v4.0 clients, there's little difference in outcome between a
@@ -1312,7 +1312,10 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
 
nfsd4_cltrack_upcall_lock(clp);
-   if (!nfsd4_umh_cltrack_upcall("create", hexid, has_session, 
grace_start))
+   ret = nfsd4_umh_cltrack_upcall("create",
+  hexid, has_session, grace_start,
+  nn->umh_token);
+   if (!ret)
set_bit(NFSD4_CLIENT_STABLE, >cl_flags);
nfsd4_cltrack_upcall_unlock(clp);
 
@@ -1324,7 +1327,9 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
 static void
 nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
 {
+   struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
char *hexid;
+   int ret;
 
if (!test_bit(NFSD4_CLIENT_STABLE, >cl_flags))
return;
@@ -1336,9 +1341,13 @@ nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
}
 
nfsd4_cltrack_upcall_lock(clp);
-   if (test_bit(NFSD4_CLIENT_STABLE, >cl_flags) &&
-   nfsd4_umh_cltrack_upcall("remove", hexid, NULL, NULL) == 0)
-   clear_bit(NFSD4_CLIENT_STABLE, >cl_flags);
+   if (test_bit(NFSD4_CLIENT_STABLE, >cl_flags)) {
+   ret = nfsd4_umh_cltrack_upcall("remove",
+  hexid, NULL, NULL,
+  nn->umh_token);
+   if (ret == 0)
+   clear_bit(NFSD4_CLIENT_STABLE, >cl_flags);
+   }
nfsd4_cltrack_upcall_unlock(clp);
 
kfree(hexid);
@@ -1347,8 +1356,9 @@ nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
 static int
 nfsd4_umh_cltrack_check(struct nfs4_client *clp)
 {
-   int ret;
+   struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
char *hexid, *has_session, *legacy;
+   int ret;
 

[RFC PATCH 5 3/7] nfsd - use service thread if not executing in init namespace

2015-03-30 Thread Ian Kent
From: Ian Kent ik...@redhat.com

If nfsd is running within a container the client tracking operations
should run within their originating container also. To do that get a
token to a service thread created within the container environment
for usermode helper calls.

Signed-off-by: Ian Kent ik...@redhat.com
Cc: Benjamin Coddington bcodd...@redhat.com
Cc: Al Viro v...@zeniv.linux.org.uk
Cc: J. Bruce Fields bfie...@fieldses.org
Cc: David Howells dhowe...@redhat.com
Cc: Trond Myklebust trond.mykleb...@primarydata.com
Cc: Oleg Nesterov onest...@redhat.com
Cc: Eric W. Biederman ebied...@xmission.com
Cc: Jeff Layton jeff.lay...@primarydata.com
---
 fs/nfsd/netns.h   |3 +++
 fs/nfsd/nfs4recover.c |   48 +++-
 fs/nfsd/nfsctl.c  |6 ++
 3 files changed, 40 insertions(+), 17 deletions(-)

diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index ea6749a..099a3c5 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -112,6 +112,9 @@ struct nfsd_net {
u32 clientid_counter;
 
struct svc_serv *nfsd_serv;
+
+   /* Namespace token */
+   int umh_token;
 };
 
 /* Simple check to find out if a given net was properly initialized */
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 1c307f0..2547edb 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -1184,7 +1184,8 @@ nfsd4_cltrack_grace_start(time_t grace_start)
 }
 
 static int
-nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1)
+nfsd4_umh_cltrack_upcall(char *cmd, char *arg,
+char *env0, char *env1, int token)
 {
char *envp[3];
char *argv[4];
@@ -1209,7 +1210,11 @@ nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char 
*env0, char *env1)
argv[2] = arg;
argv[3] = NULL;
 
-   ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
+   if (token  0)
+   ret = call_usermodehelper_service(argv[0], argv, envp,
+ token, UMH_WAIT_PROC);
+   else
+   ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
/*
 * Disable the upcall mechanism if we're getting an ENOENT or EACCES
 * error. The admin can re-enable it on the fly by using sysfs
@@ -1252,14 +1257,8 @@ nfsd4_umh_cltrack_init(struct net *net)
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
char *grace_start = nfsd4_cltrack_grace_start(nn-boot_time);
 
-   /* XXX: The usermode helper s not working in container yet. */
-   if (net != init_net) {
-   WARN(1, KERN_ERR NFSD: attempt to initialize umh client 
-   tracking in a container!\n);
-   return -EINVAL;
-   }
-
-   ret = nfsd4_umh_cltrack_upcall(init, NULL, grace_start, NULL);
+   ret = nfsd4_umh_cltrack_upcall(init, NULL,
+   grace_start, NULL, nn-umh_token);
kfree(grace_start);
return ret;
 }
@@ -1285,6 +1284,7 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
 {
char *hexid, *has_session, *grace_start;
struct nfsd_net *nn = net_generic(clp-net, nfsd_net_id);
+   int ret;
 
/*
 * With v4.0 clients, there's little difference in outcome between a
@@ -1312,7 +1312,10 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
grace_start = nfsd4_cltrack_grace_start(nn-boot_time);
 
nfsd4_cltrack_upcall_lock(clp);
-   if (!nfsd4_umh_cltrack_upcall(create, hexid, has_session, 
grace_start))
+   ret = nfsd4_umh_cltrack_upcall(create,
+  hexid, has_session, grace_start,
+  nn-umh_token);
+   if (!ret)
set_bit(NFSD4_CLIENT_STABLE, clp-cl_flags);
nfsd4_cltrack_upcall_unlock(clp);
 
@@ -1324,7 +1327,9 @@ nfsd4_umh_cltrack_create(struct nfs4_client *clp)
 static void
 nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
 {
+   struct nfsd_net *nn = net_generic(clp-net, nfsd_net_id);
char *hexid;
+   int ret;
 
if (!test_bit(NFSD4_CLIENT_STABLE, clp-cl_flags))
return;
@@ -1336,9 +1341,13 @@ nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
}
 
nfsd4_cltrack_upcall_lock(clp);
-   if (test_bit(NFSD4_CLIENT_STABLE, clp-cl_flags) 
-   nfsd4_umh_cltrack_upcall(remove, hexid, NULL, NULL) == 0)
-   clear_bit(NFSD4_CLIENT_STABLE, clp-cl_flags);
+   if (test_bit(NFSD4_CLIENT_STABLE, clp-cl_flags)) {
+   ret = nfsd4_umh_cltrack_upcall(remove,
+  hexid, NULL, NULL,
+  nn-umh_token);
+   if (ret == 0)
+   clear_bit(NFSD4_CLIENT_STABLE, clp-cl_flags);
+   }
nfsd4_cltrack_upcall_unlock(clp);
 
kfree(hexid);
@@ -1347,8 +1356,9 @@ nfsd4_umh_cltrack_remove(struct nfs4_client *clp)