Fix the NFSv4 client to safely find processes.
r340744 broke the NFSv4 client, because it replaced pfind_locked() with a call to pfind(), since pfind() acquires the sx lock for the pid hash and the NFSv4 already holds a mutex when it does the call. The patch fixes the problem by recreating a pfind_any_locked() and adding the functions pidhash_slockall() and pidhash_sunlockall to acquire/release all of the pid hash locks. These functions are then used by the NFSv4 client instead of acquiring the allproc_lock and calling pfind(). Reviewed by: kib, mjg MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D19887
This commit is contained in:
parent
e3e21edb19
commit
eeb1f3ed51
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=346217
@ -692,8 +692,6 @@ void nfsrvd_rcv(struct socket *, void *, int);
|
||||
#define NFSUNLOCKMNT(m) mtx_unlock(&((m)->nm_mtx))
|
||||
#define NFSLOCKREQUEST(r) mtx_lock(&((r)->r_mtx))
|
||||
#define NFSUNLOCKREQUEST(r) mtx_unlock(&((r)->r_mtx))
|
||||
#define NFSPROCLISTLOCK() sx_slock(&allproc_lock)
|
||||
#define NFSPROCLISTUNLOCK() sx_sunlock(&allproc_lock)
|
||||
#define NFSLOCKSOCKREQ(r) mtx_lock(&((r)->nr_mtx))
|
||||
#define NFSUNLOCKSOCKREQ(r) mtx_unlock(&((r)->nr_mtx))
|
||||
#define NFSLOCKDS(d) mtx_lock(&((d)->nfsclds_mtx))
|
||||
|
@ -1156,7 +1156,7 @@ nfscl_procdoesntexist(u_int8_t *own)
|
||||
tl.cval[2] = *own++;
|
||||
tl.cval[3] = *own++;
|
||||
pid = tl.lval;
|
||||
p = pfind(pid);
|
||||
p = pfind_any_locked(pid);
|
||||
if (p == NULL)
|
||||
return (1);
|
||||
if (p->p_stats == NULL) {
|
||||
|
@ -1789,7 +1789,13 @@ nfscl_cleanupkext(struct nfsclclient *clp, struct nfscllockownerfhhead *lhp)
|
||||
struct nfscllockowner *lp, *nlp;
|
||||
struct nfscldeleg *dp;
|
||||
|
||||
NFSPROCLISTLOCK();
|
||||
/*
|
||||
* All the pidhash locks must be acquired, since they are sx locks
|
||||
* and must be acquired before the mutexes. The pid(s) that will
|
||||
* be used aren't known yet, so all the locks need to be acquired.
|
||||
* Fortunately, this function is only performed once/sec.
|
||||
*/
|
||||
pidhash_slockall();
|
||||
NFSLOCKCLSTATE();
|
||||
LIST_FOREACH_SAFE(owp, &clp->nfsc_owner, nfsow_list, nowp) {
|
||||
LIST_FOREACH(op, &owp->nfsow_open, nfso_list) {
|
||||
@ -1816,7 +1822,7 @@ nfscl_cleanupkext(struct nfsclclient *clp, struct nfscllockownerfhhead *lhp)
|
||||
}
|
||||
}
|
||||
NFSUNLOCKCLSTATE();
|
||||
NFSPROCLISTUNLOCK();
|
||||
pidhash_sunlockall();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -193,7 +193,7 @@ procinit(void)
|
||||
pidhashtbl_lock = malloc(sizeof(*pidhashtbl_lock) * (pidhashlock + 1),
|
||||
M_PROC, M_WAITOK | M_ZERO);
|
||||
for (i = 0; i < pidhashlock + 1; i++)
|
||||
sx_init(&pidhashtbl_lock[i], "pidhash");
|
||||
sx_init_flags(&pidhashtbl_lock[i], "pidhash", SX_DUPOK);
|
||||
pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash);
|
||||
proc_zone = uma_zcreate("PROC", sched_sizeof_proc(),
|
||||
proc_ctor, proc_dtor, proc_init, proc_fini,
|
||||
@ -367,6 +367,52 @@ inferior(struct proc *p)
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shared lock all the pid hash lists.
|
||||
*/
|
||||
void
|
||||
pidhash_slockall(void)
|
||||
{
|
||||
u_long i;
|
||||
|
||||
for (i = 0; i < pidhashlock + 1; i++)
|
||||
sx_slock(&pidhashtbl_lock[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shared unlock all the pid hash lists.
|
||||
*/
|
||||
void
|
||||
pidhash_sunlockall(void)
|
||||
{
|
||||
u_long i;
|
||||
|
||||
for (i = 0; i < pidhashlock + 1; i++)
|
||||
sx_sunlock(&pidhashtbl_lock[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Similar to pfind_any(), this function finds zombies.
|
||||
*/
|
||||
struct proc *
|
||||
pfind_any_locked(pid_t pid)
|
||||
{
|
||||
struct proc *p;
|
||||
|
||||
sx_assert(PIDHASHLOCK(pid), SX_LOCKED);
|
||||
LIST_FOREACH(p, PIDHASH(pid), p_hash) {
|
||||
if (p->p_pid == pid) {
|
||||
PROC_LOCK(p);
|
||||
if (p->p_state == PRS_NEW) {
|
||||
PROC_UNLOCK(p);
|
||||
p = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Locate a process by number.
|
||||
*
|
||||
|
@ -989,8 +989,11 @@ extern struct uma_zone *proc_zone;
|
||||
|
||||
struct proc *pfind(pid_t); /* Find process by id. */
|
||||
struct proc *pfind_any(pid_t); /* Find (zombie) process by id. */
|
||||
struct proc *pfind_any_locked(pid_t pid); /* Find process by id, locked. */
|
||||
struct pgrp *pgfind(pid_t); /* Find process group by id. */
|
||||
struct proc *zpfind(pid_t); /* Find zombie process by id. */
|
||||
void pidhash_slockall(void); /* Shared lock all pid hash lists. */
|
||||
void pidhash_sunlockall(void); /* Shared unlock all pid hash lists. */
|
||||
|
||||
struct fork_req {
|
||||
int fr_flags;
|
||||
|
Loading…
Reference in New Issue
Block a user