diff options
| author | Rick Macklem <rmacklem@FreeBSD.org> | 2013-04-18 13:09:04 +0000 |
|---|---|---|
| committer | Rick Macklem <rmacklem@FreeBSD.org> | 2013-04-18 13:09:04 +0000 |
| commit | 175b3f31d328545a5bca42b0f6ac6de344e0eb4a (patch) | |
| tree | 426b7722bfd3485b471929d4c1aa32849c7396ea /sys/nfsclient | |
| parent | ca11419237a6458a92855e838724ef8c71225f0f (diff) | |
Notes
Diffstat (limited to 'sys/nfsclient')
| -rw-r--r-- | sys/nfsclient/nfs_bio.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/sys/nfsclient/nfs_bio.c b/sys/nfsclient/nfs_bio.c index b7fe832eb4c8..630a7ffe5931 100644 --- a/sys/nfsclient/nfs_bio.c +++ b/sys/nfsclient/nfs_bio.c @@ -1345,10 +1345,18 @@ nfs_asyncio(struct nfsmount *nmp, struct buf *bp, struct ucred *cred, struct thr * Commits are usually short and sweet so lets save some cpu and * leave the async daemons for more important rpc's (such as reads * and writes). + * + * Readdirplus RPCs do vget()s to acquire the vnodes for entries + * in the directory in order to update attributes. This can deadlock + * with another thread that is waiting for async I/O to be done by + * an nfsiod thread while holding a lock on one of these vnodes. + * To avoid this deadlock, don't allow the async nfsiod threads to + * perform Readdirplus RPCs. */ mtx_lock(&nfs_iod_mtx); - if (bp->b_iocmd == BIO_WRITE && (bp->b_flags & B_NEEDCOMMIT) && - (nmp->nm_bufqiods > nfs_numasync / 2)) { + if ((bp->b_iocmd == BIO_WRITE && (bp->b_flags & B_NEEDCOMMIT) && + (nmp->nm_bufqiods > nfs_numasync / 2)) || + (bp->b_vp->v_type == VDIR && (nmp->nm_flag & NFSMNT_RDIRPLUS))) { mtx_unlock(&nfs_iod_mtx); return(EIO); } |
