Index: head/sys/fs/nfs/nfsport.h =================================================================== --- head/sys/fs/nfs/nfsport.h +++ head/sys/fs/nfs/nfsport.h @@ -692,8 +692,6 @@ #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)) Index: head/sys/fs/nfsclient/nfs_clport.c =================================================================== --- head/sys/fs/nfsclient/nfs_clport.c +++ head/sys/fs/nfsclient/nfs_clport.c @@ -1156,7 +1156,7 @@ 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) { Index: head/sys/fs/nfsclient/nfs_clstate.c =================================================================== --- head/sys/fs/nfsclient/nfs_clstate.c +++ head/sys/fs/nfsclient/nfs_clstate.c @@ -1789,7 +1789,13 @@ 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 @@ } } NFSUNLOCKCLSTATE(); - NFSPROCLISTUNLOCK(); + pidhash_sunlockall(); } /* Index: head/sys/kern/kern_proc.c =================================================================== --- head/sys/kern/kern_proc.c +++ head/sys/kern/kern_proc.c @@ -193,7 +193,7 @@ 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, @@ -365,6 +365,52 @@ return (0); } 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); } /* Index: head/sys/sys/proc.h =================================================================== --- head/sys/sys/proc.h +++ head/sys/sys/proc.h @@ -989,8 +989,11 @@ 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;