summaryrefslogtreecommitdiffstats
path: root/sys/nfsclient/nfs_socket.c
diff options
context:
space:
mode:
authormohans <mohans@FreeBSD.org>2006-11-20 04:14:23 +0000
committermohans <mohans@FreeBSD.org>2006-11-20 04:14:23 +0000
commit4800f71e236b016c6ef5e788d256b822e8218ced (patch)
tree22448b979900be4a7abc581a7184beaa4c286b09 /sys/nfsclient/nfs_socket.c
parente58221ee6f2ded07307d488ff72b3c7048cdffb2 (diff)
downloadFreeBSD-src-4800f71e236b016c6ef5e788d256b822e8218ced.zip
FreeBSD-src-4800f71e236b016c6ef5e788d256b822e8218ced.tar.gz
1) Fix up locking in nfs_up() and nfs_down.
2) Reduce the acquisitions of the Giant lock in the nfs_socket.c paths significantly. - We don't need to acquire Giant before tsleeping on lbolt anymore, since jhb specialcased lbolt handling in msleep. - nfs_up() needs to acquire Giant only if printing the "server up" message. - nfs_timer() held Giant for the duration of the NFS timer processing, just because the printing of the message in nfs_down() needed it (and we acquire other locks in nfs_timer()). The acquisition of Giant is moved down into nfs_down() now, reducing the time Giant is held in that path. Reported by: Kris Kennaway
Diffstat (limited to 'sys/nfsclient/nfs_socket.c')
-rw-r--r--sys/nfsclient/nfs_socket.c69
1 files changed, 39 insertions, 30 deletions
diff --git a/sys/nfsclient/nfs_socket.c b/sys/nfsclient/nfs_socket.c
index 3b7c2b2..90e8375 100644
--- a/sys/nfsclient/nfs_socket.c
+++ b/sys/nfsclient/nfs_socket.c
@@ -488,9 +488,7 @@ nfs_reconnect(struct nfsreq *rep)
error = EINTR;
if (error == EIO || error == EINTR)
return (error);
- mtx_lock(&Giant);
(void) tsleep(&lbolt, PSOCK, "nfscon", 0);
- mtx_unlock(&Giant);
}
/*
@@ -1209,7 +1207,7 @@ tryagain:
* comes back, it will be discarded (since the req struct for it no longer
* exists).
*/
- while (rep->r_flags & R_REXMIT_INPROG) {
+ while (rep->r_flags & R_PIN_REQ) {
msleep((caddr_t)&rep->r_flags, &nfs_reqq_mtx,
(PZERO - 1), "nfsrxmt", 0);
}
@@ -1232,9 +1230,7 @@ tryagain:
* tprintf a response.
*/
if (!error) {
- mtx_lock(&Giant);
nfs_up(rep, nmp, rep->r_td, "is alive again", NFSSTA_TIMEO);
- mtx_unlock(&Giant);
}
mrep = rep->r_mrep;
md = rep->r_md;
@@ -1292,9 +1288,7 @@ tryagain:
error = 0;
waituntil = time_second + nfs3_jukebox_delay;
while (time_second < waituntil) {
- mtx_lock(&Giant);
(void) tsleep(&lbolt, PSOCK, "nqnfstry", 0);
- mtx_unlock(&Giant);
}
mtx_lock(&nfs_reqq_mtx);
if (++nfs_xid == 0)
@@ -1350,7 +1344,7 @@ nfsmout:
* lock ordering violation. The NFS client socket callback acquires
* inp_lock->nfsreq mutex and pru_send acquires inp_lock. So we drop the
* reqq mutex (and reacquire it after the pru_send()). The req structure
- * (for the rexmit) is prevented from being removed by the R_REXMIT_INPROG flag.
+ * (for the rexmit) is prevented from being removed by the R_PIN_REQ flag.
*/
void
nfs_timer(void *arg)
@@ -1364,7 +1358,6 @@ nfs_timer(void *arg)
struct timeval now;
getmicrouptime(&now);
- mtx_lock(&Giant); /* nfs_down -> tprintf */
mtx_lock(&nfs_reqq_mtx);
TAILQ_FOREACH(rep, &nfs_reqq, r_chain) {
nmp = rep->r_nmp;
@@ -1393,13 +1386,18 @@ nfs_timer(void *arg)
if (nmp->nm_tprintf_initial_delay != 0 &&
(rep->r_rexmit > 2 || (rep->r_flags & R_RESENDERR)) &&
rep->r_lastmsg + nmp->nm_tprintf_delay < now.tv_sec) {
+ rep->r_lastmsg = now.tv_sec;
+ rep->r_flags |= R_PIN_REQ;
mtx_unlock(&rep->r_mtx);
mtx_unlock(&nmp->nm_mtx);
- rep->r_lastmsg = now.tv_sec;
+ mtx_unlock(&nfs_reqq_mtx);
nfs_down(rep, nmp, rep->r_td, "not responding",
0, NFSSTA_TIMEO);
+ mtx_lock(&nfs_reqq_mtx);
mtx_lock(&nmp->nm_mtx);
mtx_lock(&rep->r_mtx);
+ rep->r_flags &= ~R_PIN_REQ;
+ wakeup((caddr_t)&rep->r_flags);
}
if (rep->r_rtt >= 0) {
rep->r_rtt++;
@@ -1463,7 +1461,7 @@ nfs_timer(void *arg)
* removed in nfs_request().
*/
mtx_lock(&rep->r_mtx);
- rep->r_flags |= R_REXMIT_INPROG;
+ rep->r_flags |= R_PIN_REQ;
mtx_unlock(&rep->r_mtx);
mtx_unlock(&nfs_reqq_mtx);
NET_LOCK_GIANT();
@@ -1478,7 +1476,7 @@ nfs_timer(void *arg)
mtx_lock(&nfs_reqq_mtx);
mtx_lock(&nmp->nm_mtx);
mtx_lock(&rep->r_mtx);
- rep->r_flags &= ~R_REXMIT_INPROG;
+ rep->r_flags &= ~R_PIN_REQ;
wakeup((caddr_t)&rep->r_flags);
if (error) {
if (NFSIGNORE_SOERROR(nmp->nm_soflags, error))
@@ -1514,7 +1512,6 @@ nfs_timer(void *arg)
}
}
mtx_unlock(&nfs_reqq_mtx);
- mtx_unlock(&Giant); /* nfs_down -> tprintf */
callout_reset(&nfs_callout, nfs_ticks, nfs_timer, NULL);
}
@@ -1552,9 +1549,7 @@ nfs_nmcancelreqs(nmp)
mtx_unlock(&nfs_reqq_mtx);
if (req == NULL)
return (0);
- mtx_lock(&Giant);
tsleep(&lbolt, PSOCK, "nfscancel", 0);
- mtx_unlock(&Giant);
}
return (EBUSY);
}
@@ -1864,28 +1859,33 @@ nfs_down(rep, nmp, td, msg, error, flags)
const char *msg;
int error, flags;
{
-
- GIANT_REQUIRED; /* nfs_msg */
-
if (nmp == NULL)
return;
+ mtx_lock(&nmp->nm_mtx);
if ((flags & NFSSTA_TIMEO) && !(nmp->nm_state & NFSSTA_TIMEO)) {
+ nmp->nm_state |= NFSSTA_TIMEO;
+ mtx_unlock(&nmp->nm_mtx);
vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
VQ_NOTRESP, 0);
- nmp->nm_state |= NFSSTA_TIMEO;
- }
+ } else
+ mtx_unlock(&nmp->nm_mtx);
#ifdef NFSSTA_LOCKTIMEO
+ mtx_lock(&nmp->nm_mtx);
if ((flags & NFSSTA_LOCKTIMEO) && !(nmp->nm_state & NFSSTA_LOCKTIMEO)) {
+ nmp->nm_state |= NFSSTA_LOCKTIMEO;
+ mtx_unlock(&nmp->nm_mtx);
vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
VQ_NOTRESPLOCK, 0);
- nmp->nm_state |= NFSSTA_LOCKTIMEO;
- }
+ } else
+ mtx_unlock(&nmp->nm_mtx);
#endif
mtx_lock(&rep->r_mtx);
if (rep)
rep->r_flags |= R_TPRINTFMSG;
mtx_unlock(&rep->r_mtx);
+ mtx_lock(&Giant);
nfs_msg(td, nmp->nm_mountp->mnt_stat.f_mntfromname, msg, error);
+ mtx_unlock(&Giant);
}
void
@@ -1896,25 +1896,34 @@ nfs_up(rep, nmp, td, msg, flags)
const char *msg;
int flags;
{
-
- GIANT_REQUIRED; /* nfs_msg */
-
- if (nmp == NULL)
+ if (nmp == NULL || rep == NULL)
return;
mtx_lock(&rep->r_mtx);
- if ((rep == NULL) || (rep->r_flags & R_TPRINTFMSG) != 0)
+ if ((rep->r_flags & R_TPRINTFMSG) != 0) {
+ mtx_unlock(&rep->r_mtx);
+ mtx_lock(&Giant);
nfs_msg(td, nmp->nm_mountp->mnt_stat.f_mntfromname, msg, 0);
- mtx_unlock(&rep->r_mtx);
+ mtx_unlock(&Giant);
+ } else
+ mtx_unlock(&rep->r_mtx);
+
+ mtx_lock(&nmp->nm_mtx);
if ((flags & NFSSTA_TIMEO) && (nmp->nm_state & NFSSTA_TIMEO)) {
nmp->nm_state &= ~NFSSTA_TIMEO;
+ mtx_unlock(&nmp->nm_mtx);
vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
VQ_NOTRESP, 1);
- }
+ } else
+ mtx_unlock(&nmp->nm_mtx);
+
#ifdef NFSSTA_LOCKTIMEO
+ mtx_lock(&nmp->nm_mtx);
if ((flags & NFSSTA_LOCKTIMEO) && (nmp->nm_state & NFSSTA_LOCKTIMEO)) {
nmp->nm_state &= ~NFSSTA_LOCKTIMEO;
+ mtx_unlock(&nmp->nm_mtx);
vfs_event_signal(&nmp->nm_mountp->mnt_stat.f_fsid,
VQ_NOTRESPLOCK, 1);
- }
+ } else
+ mtx_unlock(&nmp->nm_mtx);
#endif
}
OpenPOWER on IntegriCloud