Index: sys/fs/nfsclient/nfs_clport.c =================================================================== --- sys/fs/nfsclient/nfs_clport.c +++ sys/fs/nfsclient/nfs_clport.c @@ -99,6 +99,7 @@ static void nfscl_warn_fileid(struct nfsmount *, struct nfsvattr *, struct nfsvattr *); +static struct proc *nfscl_pfind(pid_t); /* * Comparison function for vfs_hash functions. @@ -1131,6 +1132,36 @@ } /* + * This is a variant of _pfind() that can only be called when all pid hash + * lists are locked. It must be done this way, since nfscl_procdoesntexist() + * must be called with locked mutexes and the sx locks for the hash lists + * must be acquired before the mutexes. + * It will return Zombie processes. + */ +static struct proc * +nfscl_pfind(pid_t pid) +{ + struct proc *p; + + p = curproc; + if (p->p_pid == pid) { + PROC_LOCK(p); + return (p); + } + 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); +} + +/* * Check to see if the process for this owner exists. Return 1 if it doesn't * and 0 otherwise. */ @@ -1157,7 +1188,7 @@ tl.cval[2] = *own++; tl.cval[3] = *own++; pid = tl.lval; - p = pfind(pid); + p = nfscl_pfind(pid); if (p == NULL) return (1); if (p->p_stats == NULL) { Index: sys/fs/nfsclient/nfs_clstate.c =================================================================== --- sys/fs/nfsclient/nfs_clstate.c +++ sys/fs/nfsclient/nfs_clstate.c @@ -1788,8 +1788,16 @@ struct nfsclopen *op; struct nfscllockowner *lp, *nlp; struct nfscldeleg *dp; + int i; - 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. + */ + for (i = 0; i < pidhashlock + 1; i++) + sx_slock(&pidhashtbl_lock[i]); NFSLOCKCLSTATE(); LIST_FOREACH_SAFE(owp, &clp->nfsc_owner, nfsow_list, nowp) { LIST_FOREACH(op, &owp->nfsow_open, nfso_list) { @@ -1816,7 +1824,8 @@ } } NFSUNLOCKCLSTATE(); - NFSPROCLISTUNLOCK(); + for (i = 0; i < pidhashlock + 1; i++) + sx_sunlock(&pidhashtbl_lock[i]); } /* Index: sys/kern/kern_proc.c =================================================================== --- sys/kern/kern_proc.c +++ sys/kern/kern_proc.c @@ -178,6 +178,7 @@ procinit(void) { u_long i; + char buf[16]; sx_init(&allproc_lock, "allproc"); sx_init(&zombproc_lock, "zombproc"); @@ -192,8 +193,10 @@ pidhashlock--; 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"); + for (i = 0; i < pidhashlock + 1; i++) { + snprintf(buf, sizeof(buf), "pidhash%ju", (uintmax_t)i); + sx_init(&pidhashtbl_lock[i], buf); + } pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash); proc_zone = uma_zcreate("PROC", sched_sizeof_proc(), proc_ctor, proc_dtor, proc_init, proc_fini,