Skip to content

Commit

Permalink
SUNRPC: change sp_nrthreads to atomic_t
Browse files Browse the repository at this point in the history
Using an atomic_t avoids the need to take a spinlock (which can soon be
removed).

Choosing a thread to kill needs to be careful as we cannot set the "die
now" bit atomically with the test on the count.  Instead we temporarily
increase the count.

Signed-off-by: NeilBrown <neilb@suse.de>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
  • Loading branch information
NeilBrown authored and Chuck Lever committed Oct 16, 2023
1 parent 9a0e6ac commit 2e8fc92
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 24 deletions.
11 changes: 5 additions & 6 deletions fs/nfsd/nfssvc.c
Original file line number Diff line number Diff line change
Expand Up @@ -713,14 +713,13 @@ int nfsd_nrpools(struct net *net)

int nfsd_get_nrthreads(int n, int *nthreads, struct net *net)
{
int i = 0;
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
struct svc_serv *serv = nn->nfsd_serv;
int i;

if (nn->nfsd_serv != NULL) {
for (i = 0; i < nn->nfsd_serv->sv_nrpools && i < n; i++)
nthreads[i] = nn->nfsd_serv->sv_pools[i].sp_nrthreads;
}

if (serv)
for (i = 0; i < serv->sv_nrpools && i < n; i++)
nthreads[i] = atomic_read(&serv->sv_pools[i].sp_nrthreads);
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion include/linux/sunrpc/svc.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct svc_pool {
unsigned int sp_id; /* pool id; also node id on NUMA */
spinlock_t sp_lock; /* protects all fields */
struct lwq sp_xprts; /* pending transports */
unsigned int sp_nrthreads; /* # of threads in pool */
atomic_t sp_nrthreads; /* # of threads in pool */
struct list_head sp_all_threads; /* all server threads */
struct llist_head sp_idle_threads; /* idle server threads */

Expand Down
37 changes: 20 additions & 17 deletions net/sunrpc/svc.c
Original file line number Diff line number Diff line change
Expand Up @@ -681,8 +681,8 @@ svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node)
serv->sv_nrthreads += 1;
spin_unlock_bh(&serv->sv_lock);

atomic_inc(&pool->sp_nrthreads);
spin_lock_bh(&pool->sp_lock);
pool->sp_nrthreads++;
list_add_rcu(&rqstp->rq_all, &pool->sp_all_threads);
spin_unlock_bh(&pool->sp_lock);
return rqstp;
Expand Down Expand Up @@ -727,32 +727,37 @@ svc_pool_next(struct svc_serv *serv, struct svc_pool *pool, unsigned int *state)
}

static struct svc_pool *
svc_pool_victim(struct svc_serv *serv, struct svc_pool *pool, unsigned int *state)
svc_pool_victim(struct svc_serv *serv, struct svc_pool *target_pool,
unsigned int *state)
{
struct svc_pool *pool;
unsigned int i;

retry:
pool = target_pool;

if (pool != NULL) {
spin_lock_bh(&pool->sp_lock);
if (pool->sp_nrthreads)
if (atomic_inc_not_zero(&pool->sp_nrthreads))
goto found_pool;
spin_unlock_bh(&pool->sp_lock);
return NULL;
} else {
for (i = 0; i < serv->sv_nrpools; i++) {
pool = &serv->sv_pools[--(*state) % serv->sv_nrpools];
spin_lock_bh(&pool->sp_lock);
if (pool->sp_nrthreads)
if (atomic_inc_not_zero(&pool->sp_nrthreads))
goto found_pool;
spin_unlock_bh(&pool->sp_lock);
}
return NULL;
}

found_pool:
set_bit(SP_VICTIM_REMAINS, &pool->sp_flags);
set_bit(SP_NEED_VICTIM, &pool->sp_flags);
spin_unlock_bh(&pool->sp_lock);
return pool;
if (!atomic_dec_and_test(&pool->sp_nrthreads))
return pool;
/* Nothing left in this pool any more */
clear_bit(SP_NEED_VICTIM, &pool->sp_flags);
clear_bit(SP_VICTIM_REMAINS, &pool->sp_flags);
goto retry;
}

static int
Expand Down Expand Up @@ -828,13 +833,10 @@ svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
int
svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
{
if (pool == NULL) {
if (!pool)
nrservs -= serv->sv_nrthreads;
} else {
spin_lock_bh(&pool->sp_lock);
nrservs -= pool->sp_nrthreads;
spin_unlock_bh(&pool->sp_lock);
}
else
nrservs -= atomic_read(&pool->sp_nrthreads);

if (nrservs > 0)
return svc_start_kthreads(serv, pool, nrservs);
Expand Down Expand Up @@ -921,10 +923,11 @@ svc_exit_thread(struct svc_rqst *rqstp)
struct svc_pool *pool = rqstp->rq_pool;

spin_lock_bh(&pool->sp_lock);
pool->sp_nrthreads--;
list_del_rcu(&rqstp->rq_all);
spin_unlock_bh(&pool->sp_lock);

atomic_dec(&pool->sp_nrthreads);

spin_lock_bh(&serv->sv_lock);
serv->sv_nrthreads -= 1;
spin_unlock_bh(&serv->sv_lock);
Expand Down

0 comments on commit 2e8fc92

Please sign in to comment.