Index: nfs/nfs_lock.c =================================================================== --- nfs/nfs_lock.c +++ nfs/nfs_lock.c @@ -81,6 +81,7 @@ static struct cdev *nfslock_dev; static struct mtx nfslock_mtx; +static struct mtx nfsinfolock_mtx; static int nfslock_isopen; static TAILQ_HEAD(,__lock_msg) nfslock_list; @@ -165,14 +166,13 @@ return (error); } +/* Consumes *lm2. */ static int -nfslock_send(struct __lock_msg *lm) +nfslock_send(struct __lock_msg *lm, struct __lock_msg *lm2) { - struct __lock_msg *lm2; int error; error = 0; - lm2 = malloc(sizeof *lm2, M_NFSLOCK, M_WAITOK); mtx_lock(&nfslock_mtx); if (nfslock_isopen) { memcpy(lm2, lm, sizeof *lm2); @@ -205,6 +205,7 @@ if (bootverbose) printf("nfslock: pseudo-device\n"); mtx_init(&nfslock_mtx, "nfslock", NULL, MTX_DEF); + mtx_init(&nfsinfolock_mtx, "nfsinfolock", NULL, MTX_DEF); TAILQ_INIT(&nfslock_list); nlminfo_release_p = nlminfo_release; nfslock_dev = make_dev(&nfslock_cdevsw, 0, @@ -244,6 +245,8 @@ struct proc *p; struct nfsmount *nmp; struct timeval boottime; + struct nlminfo *nlminf; + struct __lock_msg *lm2; td = curthread; p = td->td_proc; @@ -279,13 +282,17 @@ msg.lm_version = LOCKD_MSG_VERSION; msg.lm_msg_ident.pid = p->p_pid; - mtx_lock(&Giant); + /* Malloc structures needed before acquiring the mutex. */ + lm2 = malloc(sizeof *lm2, M_NFSLOCK, M_WAITOK); + nlminf = malloc(sizeof(struct nlminfo), M_NLMINFO, M_WAITOK | M_ZERO); + + mtx_lock(&nfsinfolock_mtx); /* * if there is no nfsowner table yet, allocate one. */ if (p->p_nlminfo == NULL) { - p->p_nlminfo = malloc(sizeof(struct nlminfo), - M_NLMINFO, M_WAITOK | M_ZERO); + p->p_nlminfo = nlminf; + nlminf = NULL; p->p_nlminfo->pid_start = p->p_stats->p_start; getboottime(&boottime); timevaladd(&p->p_nlminfo->pid_start, &boottime); @@ -298,8 +305,10 @@ msg.lm_getlk = ap->a_op == F_GETLK; cru2x(td->td_ucred, &msg.lm_cred); - for (;;) { - error = nfslock_send(&msg); + do { + KASSERT(lm2 != NULL, ("nfs_dolock: lm2 NULL")); + error = nfslock_send(&msg, lm2); + lm2 = NULL; /* Consumed by nfslock_send(). */ if (error) goto out; @@ -322,19 +331,19 @@ * permit aborting, the lock attempt would "get lost" * and the lock would get stuck in the locked state. */ - error = tsleep(p->p_nlminfo, PUSER, "lockd", 20*hz); - if (error != 0) { - if (error == EWOULDBLOCK) { - /* - * We timed out, so we rewrite the request - * to the fifo. - */ - continue; - } - - break; + error = msleep(p->p_nlminfo, &nfsinfolock_mtx, PUSER | PDROP, + "lockd", 20*hz); + if (error == EWOULDBLOCK) { + /* + * We timed out, so we rewrite the request + * to the fifo. + */ + lm2 = malloc(sizeof *lm2, M_NFSLOCK, M_WAITOK); } + mtx_lock(&nfsinfolock_mtx); + } while (error == EWOULDBLOCK); + if (error == 0) { if (msg.lm_getlk && p->p_nlminfo->retcode == 0) { if (p->p_nlminfo->set_getlk_pid) { fl->l_sysid = 0; /* XXX */ @@ -344,10 +353,10 @@ } } error = p->p_nlminfo->retcode; - break; } out: - mtx_unlock(&Giant); + mtx_unlock(&nfsinfolock_mtx); + free(nlminf, M_NLMINFO); /* If not consumed above. */ return (error); } @@ -367,6 +376,7 @@ /* Find the process, set its return errno and wake it up. */ if ((targetp = pfind(ansp->la_msg_ident.pid)) == NULL) return (ESRCH); + mtx_lock(&nfsinfolock_mtx); /* verify the pid hasn't been reused (if we can), and it isn't waiting * for an answer from a more recent request. We return an EPIPE if @@ -378,6 +388,7 @@ (timevalcmp(&targetp->p_nlminfo->pid_start, &ansp->la_msg_ident.pid_start, !=) || targetp->p_nlminfo->msg_seq != ansp->la_msg_ident.msg_seq))) { + mtx_unlock(&nfsinfolock_mtx); PROC_UNLOCK(targetp); return (EPIPE); } @@ -388,6 +399,7 @@ wakeup(targetp->p_nlminfo); + mtx_unlock(&nfsinfolock_mtx); PROC_UNLOCK(targetp); return (0); }