Re: [RFC PATCH 5 3/7] nfsd - use service thread if not executing in init namespace
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
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
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
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
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
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
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
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)