Skip to content

Commit 9f28a97

Browse files
neilbrownchucklever
authored andcommitted
nfsd: separate nfsd_last_thread() from nfsd_put()
Now that the last nfsd thread is stopped by an explicit act of calling svc_set_num_threads() with a count of zero, we only have a limited number of places that can happen, and don't need to call nfsd_last_thread() in nfsd_put() So separate that out and call it at the two places where the number of threads is set to zero. Move the clearing of ->nfsd_serv and the call to svc_xprt_destroy_all() into nfsd_last_thread(), as they are really part of the same action. nfsd_put() is now a thin wrapper around svc_put(), so make it a static inline. nfsd_put() cannot be called after nfsd_last_thread(), so in a couple of places we have to use svc_put() instead. Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
1 parent 18e4cf9 commit 9f28a97

File tree

2 files changed

+25
-34
lines changed

2 files changed

+25
-34
lines changed

fs/nfsd/nfsd.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,12 @@ int nfsd_pool_stats_open(struct inode *, struct file *);
9696
int nfsd_pool_stats_release(struct inode *, struct file *);
9797
void nfsd_shutdown_threads(struct net *net);
9898

99-
void nfsd_put(struct net *net);
99+
static inline void nfsd_put(struct net *net)
100+
{
101+
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
102+
103+
svc_put(nn->nfsd_serv);
104+
}
100105

101106
bool i_am_nfsd(void);
102107

fs/nfsd/nfssvc.c

Lines changed: 19 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -542,9 +542,14 @@ static struct notifier_block nfsd_inet6addr_notifier = {
542542
/* Only used under nfsd_mutex, so this atomic may be overkill: */
543543
static atomic_t nfsd_notifier_refcount = ATOMIC_INIT(0);
544544

545-
static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
545+
static void nfsd_last_thread(struct net *net)
546546
{
547547
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
548+
struct svc_serv *serv = nn->nfsd_serv;
549+
550+
spin_lock(&nfsd_notifier_lock);
551+
nn->nfsd_serv = NULL;
552+
spin_unlock(&nfsd_notifier_lock);
548553

549554
/* check if the notifier still has clients */
550555
if (atomic_dec_return(&nfsd_notifier_refcount) == 0) {
@@ -554,6 +559,8 @@ static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
554559
#endif
555560
}
556561

562+
svc_xprt_destroy_all(serv, net);
563+
557564
/*
558565
* write_ports can create the server without actually starting
559566
* any threads--if we get shut down before any threads are
@@ -644,7 +651,8 @@ void nfsd_shutdown_threads(struct net *net)
644651
svc_get(serv);
645652
/* Kill outstanding nfsd threads */
646653
svc_set_num_threads(serv, NULL, 0);
647-
nfsd_put(net);
654+
nfsd_last_thread(net);
655+
svc_put(serv);
648656
mutex_unlock(&nfsd_mutex);
649657
}
650658

@@ -674,9 +682,6 @@ int nfsd_create_serv(struct net *net)
674682
serv->sv_maxconn = nn->max_connections;
675683
error = svc_bind(serv, net);
676684
if (error < 0) {
677-
/* NOT nfsd_put() as notifiers (see below) haven't
678-
* been set up yet.
679-
*/
680685
svc_put(serv);
681686
return error;
682687
}
@@ -719,29 +724,6 @@ int nfsd_get_nrthreads(int n, int *nthreads, struct net *net)
719724
return 0;
720725
}
721726

722-
/* This is the callback for kref_put() below.
723-
* There is no code here as the first thing to be done is
724-
* call svc_shutdown_net(), but we cannot get the 'net' from
725-
* the kref. So do all the work when kref_put returns true.
726-
*/
727-
static void nfsd_noop(struct kref *ref)
728-
{
729-
}
730-
731-
void nfsd_put(struct net *net)
732-
{
733-
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
734-
735-
if (kref_put(&nn->nfsd_serv->sv_refcnt, nfsd_noop)) {
736-
svc_xprt_destroy_all(nn->nfsd_serv, net);
737-
nfsd_last_thread(nn->nfsd_serv, net);
738-
svc_destroy(&nn->nfsd_serv->sv_refcnt);
739-
spin_lock(&nfsd_notifier_lock);
740-
nn->nfsd_serv = NULL;
741-
spin_unlock(&nfsd_notifier_lock);
742-
}
743-
}
744-
745727
int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
746728
{
747729
int i = 0;
@@ -792,7 +774,7 @@ int nfsd_set_nrthreads(int n, int *nthreads, struct net *net)
792774
if (err)
793775
break;
794776
}
795-
nfsd_put(net);
777+
svc_put(nn->nfsd_serv);
796778
return err;
797779
}
798780

@@ -807,6 +789,7 @@ nfsd_svc(int nrservs, struct net *net, const struct cred *cred)
807789
int error;
808790
bool nfsd_up_before;
809791
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
792+
struct svc_serv *serv;
810793

811794
mutex_lock(&nfsd_mutex);
812795
dprintk("nfsd: creating service\n");
@@ -826,22 +809,25 @@ nfsd_svc(int nrservs, struct net *net, const struct cred *cred)
826809
goto out;
827810

828811
nfsd_up_before = nn->nfsd_net_up;
812+
serv = nn->nfsd_serv;
829813

830814
error = nfsd_startup_net(net, cred);
831815
if (error)
832816
goto out_put;
833-
error = svc_set_num_threads(nn->nfsd_serv, NULL, nrservs);
817+
error = svc_set_num_threads(serv, NULL, nrservs);
834818
if (error)
835819
goto out_shutdown;
836-
error = nn->nfsd_serv->sv_nrthreads;
820+
error = serv->sv_nrthreads;
821+
if (error == 0)
822+
nfsd_last_thread(net);
837823
out_shutdown:
838824
if (error < 0 && !nfsd_up_before)
839825
nfsd_shutdown_net(net);
840826
out_put:
841827
/* Threads now hold service active */
842828
if (xchg(&nn->keep_active, 0))
843-
nfsd_put(net);
844-
nfsd_put(net);
829+
svc_put(serv);
830+
svc_put(serv);
845831
out:
846832
mutex_unlock(&nfsd_mutex);
847833
return error;

0 commit comments

Comments
 (0)