diff options
author | rmacklem <rmacklem@FreeBSD.org> | 2013-11-09 21:24:56 +0000 |
---|---|---|
committer | rmacklem <rmacklem@FreeBSD.org> | 2013-11-09 21:24:56 +0000 |
commit | 1ab8f0512b19c420fa538e3d691e86cee0b98f4d (patch) | |
tree | d75ef61ee7f8712e0b8168e1ccf150bc047d25f8 /sys/fs/nfs | |
parent | 0ab3bf57caf5ccc0b10318a3208854b6c0f7263e (diff) | |
download | FreeBSD-src-1ab8f0512b19c420fa538e3d691e86cee0b98f4d.zip FreeBSD-src-1ab8f0512b19c420fa538e3d691e86cee0b98f4d.tar.gz |
Fix an NFSv4.1 client specific case where a forced dismount would hang.
The hang occurred in nfsv4_setsequence() when it couldn't find an
available session slot and is fixed by checking for a forced dismount
in progress and just returning for this case.
MFC after: 1 month
Diffstat (limited to 'sys/fs/nfs')
-rw-r--r-- | sys/fs/nfs/nfs_commonsubs.c | 20 | ||||
-rw-r--r-- | sys/fs/nfs/nfs_var.h | 3 |
2 files changed, 18 insertions, 5 deletions
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c index b60b0eb..0ee06bd 100644 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -3693,8 +3693,8 @@ nfsv4_seqsess_cacherep(uint32_t slotid, struct nfsslot *slots, struct mbuf *rep) * Generate the xdr for an NFSv4.1 Sequence Operation. */ APPLESTATIC void -nfsv4_setsequence(struct nfsrv_descript *nd, struct nfsclsession *sep, - int dont_replycache) +nfsv4_setsequence(struct nfsmount *nmp, struct nfsrv_descript *nd, + struct nfsclsession *sep, int dont_replycache) { uint32_t *tl, slotseq = 0; int i, maxslot, slotpos; @@ -3717,9 +3717,21 @@ nfsv4_setsequence(struct nfsrv_descript *nd, struct nfsclsession *sep, } bitval <<= 1; } - if (slotpos == -1) + if (slotpos == -1) { + /* + * If a forced dismount is in progress, just return. + * This RPC attempt will fail when it calls + * newnfs_request(). + */ + if ((nmp->nm_mountp->mnt_kern_flag & MNTK_UNMOUNTF) + != 0) { + mtx_unlock(&sep->nfsess_mtx); + return; + } + /* Wake up once/sec, to check for a forced dismount. */ (void)mtx_sleep(&sep->nfsess_slots, &sep->nfsess_mtx, - PZERO, "nfsclseq", 0); + PZERO, "nfsclseq", hz); + } } while (slotpos == -1); /* Now, find the highest slot in use. (nfsc_slots is 64bits) */ bitval = 1; diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h index 1edb8a3..f6a974e 100644 --- a/sys/fs/nfs/nfs_var.h +++ b/sys/fs/nfs/nfs_var.h @@ -265,7 +265,8 @@ int nfsv4_getipaddr(struct nfsrv_descript *, struct sockaddr_storage *, int nfsv4_seqsession(uint32_t, uint32_t, uint32_t, struct nfsslot *, struct mbuf **, uint16_t); void nfsv4_seqsess_cacherep(uint32_t, struct nfsslot *, struct mbuf *); -void nfsv4_setsequence(struct nfsrv_descript *, struct nfsclsession *, int); +void nfsv4_setsequence(struct nfsmount *, struct nfsrv_descript *, + struct nfsclsession *, int); void nfsv4_freeslot(struct nfsclsession *, int); /* nfs_clcomsubs.c */ |