From 17c53e4a2899c34e9ce6f7cf2a5f0d481ec6335b Mon Sep 17 00:00:00 2001 From: Mohan Srinivasan Date: Tue, 25 Sep 2007 21:08:49 +0000 Subject: [PATCH] Fix for a very rare race, caused by the nfsiod wakeup and nfsiod idle timeout occurring at exactly the same time. If this happens, the nfsiod exits although there may be a queued async IO request for it. Found by : Kris Kennaway Approved by: re --- sys/nfsclient/nfs_bio.c | 7 +++++++ sys/nfsclient/nfs_nfsiod.c | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c index e1a74536c498..8066ac20c782 100644 --- a/sys/nfsclient/nfs_bio.c +++ b/sys/nfsclient/nfs_bio.c @@ -1453,6 +1453,13 @@ nfs_asyncio(struct nfsmount *nmp, struct buf *bp, struct ucred *cred, struct thr } } + /* We might have lost our nfsiod */ + if (nmp->nm_bufqiods == 0) { + NFS_DPF(ASYNCIO, + ("nfs_asyncio: no iods after mount %p queue was drained, looping\n", nmp)); + goto again; + } + if (bp->b_iocmd == BIO_READ) { if (bp->b_rcred == NOCRED && cred != NOCRED) bp->b_rcred = crhold(cred); diff --git a/sys/nfsclient/nfs_nfsiod.c b/sys/nfsclient/nfs_nfsiod.c index e219c711f3c6..ac98732c76b5 100644 --- a/sys/nfsclient/nfs_nfsiod.c +++ b/sys/nfsclient/nfs_nfsiod.c @@ -229,9 +229,8 @@ nfssvc_iod(void *instance) * Main loop */ for (;;) { - while (((nmp = nfs_iodmount[myiod]) == NULL - || !TAILQ_FIRST(&nmp->nm_bufq)) - && error == 0) { + while (((nmp = nfs_iodmount[myiod]) == NULL) + || !TAILQ_FIRST(&nmp->nm_bufq)) { if (myiod >= nfs_iodmax) goto finish; if (nmp) @@ -244,6 +243,17 @@ nfssvc_iod(void *instance) timo = (myiod < nfs_iodmin) ? 0 : nfs_iodmaxidle * hz; error = msleep(&nfs_iodwant[myiod], &nfs_iod_mtx, PWAIT | PCATCH, "-", timo); + if (error) { + nmp = nfs_iodmount[myiod]; + /* + * Rechecking the nm_bufq closes a rare race where the + * nfsiod is woken up at the exact time the idle timeout + * fires + */ + if (nmp && TAILQ_FIRST(&nmp->nm_bufq)) + error = 0; + break; + } } if (error) break;